summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--.htaccess35
-rw-r--r--Bugzilla.pm104
-rw-r--r--Bugzilla/Arecibo.pm301
-rw-r--r--Bugzilla/Attachment.pm52
-rw-r--r--Bugzilla/Attachment/PatchReader.pm77
-rw-r--r--Bugzilla/Auth.pm9
-rw-r--r--Bugzilla/Bug.pm238
-rw-r--r--Bugzilla/BugMail.pm147
-rw-r--r--Bugzilla/BugUrl.pm1
-rw-r--r--Bugzilla/BugUrl/GitHub.pm36
-rw-r--r--Bugzilla/CGI.pm13
-rw-r--r--Bugzilla/Comment.pm5
-rw-r--r--Bugzilla/Component.pm6
-rw-r--r--Bugzilla/Config.pm6
-rw-r--r--Bugzilla/Config/Advanced.pm12
-rw-r--r--Bugzilla/Config/Auth.pm6
-rw-r--r--Bugzilla/Constants.pm36
-rw-r--r--Bugzilla/DB.pm8
-rw-r--r--Bugzilla/DB/Oracle.pm6
-rw-r--r--Bugzilla/DB/Schema.pm39
-rw-r--r--Bugzilla/Error.pm93
-rw-r--r--Bugzilla/Field.pm178
-rw-r--r--Bugzilla/Flag.pm88
-rw-r--r--Bugzilla/FlagType.pm13
-rw-r--r--Bugzilla/Group.pm5
-rw-r--r--Bugzilla/Hook.pm49
-rw-r--r--Bugzilla/Install.pm4
-rw-r--r--Bugzilla/Install/DB.pm109
-rw-r--r--Bugzilla/Install/Filesystem.pm16
-rw-r--r--Bugzilla/Install/Util.pm6
-rw-r--r--Bugzilla/JobQueue.pm60
-rw-r--r--Bugzilla/JobQueue/Runner.pm25
-rw-r--r--Bugzilla/Mailer.pm60
-rw-r--r--Bugzilla/Migrate.pm2
-rw-r--r--Bugzilla/Object.pm56
-rw-r--r--Bugzilla/PatchReader.pm117
-rw-r--r--Bugzilla/PatchReader/AddCVSContext.pm226
-rw-r--r--Bugzilla/PatchReader/Base.pm23
-rw-r--r--Bugzilla/PatchReader/CVSClient.pm48
-rw-r--r--Bugzilla/PatchReader/DiffPrinter/raw.pm61
-rw-r--r--Bugzilla/PatchReader/DiffPrinter/template.pm119
-rw-r--r--Bugzilla/PatchReader/FilterPatch.pm43
-rw-r--r--Bugzilla/PatchReader/FixPatchRoot.pm130
-rw-r--r--Bugzilla/PatchReader/NarrowPatch.pm44
-rw-r--r--Bugzilla/PatchReader/PatchInfoGrabber.pm45
-rw-r--r--Bugzilla/PatchReader/Raw.pm268
-rw-r--r--Bugzilla/Product.pm13
-rw-r--r--Bugzilla/Search.pm336
-rw-r--r--Bugzilla/Search/Clause.pm7
-rw-r--r--Bugzilla/Search/ClauseGroup.pm96
-rw-r--r--Bugzilla/Search/Quicksearch.pm10
-rw-r--r--Bugzilla/Search/Recent.pm13
-rw-r--r--Bugzilla/Send/Sendmail.pm95
-rw-r--r--Bugzilla/Template.pm115
-rw-r--r--Bugzilla/Template/Context.pm7
-rw-r--r--Bugzilla/Token.pm2
-rw-r--r--Bugzilla/User.pm75
-rw-r--r--Bugzilla/UserAgent.pm249
-rw-r--r--Bugzilla/Util.pm42
-rw-r--r--Bugzilla/WebService.pm12
-rw-r--r--Bugzilla/WebService/Bug.pm266
-rw-r--r--Bugzilla/WebService/Product.pm34
-rw-r--r--Bugzilla/WebService/Server/JSONRPC.pm5
-rw-r--r--Bugzilla/WebService/Server/XMLRPC.pm7
-rw-r--r--Bugzilla/WebService/User.pm117
-rw-r--r--Bugzilla/WebService/Util.pm36
-rwxr-xr-xarecibo.pl65
-rwxr-xr-xattachment.cgi18
-rwxr-xr-xbuglist.cgi44
-rw-r--r--bzr-update.sh9
-rwxr-xr-xchart.cgi3
-rwxr-xr-xcollectstats.pl3
-rwxr-xr-xconfig.cgi2
-rwxr-xr-xcontrib/addcustomfield.pl62
-rwxr-xr-xcontrib/fix_comment_text.pl75
-rwxr-xr-xcontrib/moco-ldap-check.pl542
-rwxr-xr-xcontrib/nagios_blocker_checker.pl90
-rwxr-xr-xcontrib/new-yui3.pl80
-rwxr-xr-xcontrib/recode.pl2
-rw-r--r--contrib/reorg-tools/README9
-rwxr-xr-xcontrib/reorg-tools/bmo-plan.txt82
-rwxr-xr-xcontrib/reorg-tools/fix_all_open_status_queries.pl140
-rwxr-xr-xcontrib/reorg-tools/fixgroupqueries.pl119
-rwxr-xr-xcontrib/reorg-tools/fixqueries.pl132
-rwxr-xr-xcontrib/reorg-tools/migrate_crash_signatures.pl126
-rwxr-xr-xcontrib/reorg-tools/migrate_orange_bugs.pl154
-rwxr-xr-xcontrib/reorg-tools/move_flag_types.pl168
-rwxr-xr-xcontrib/reorg-tools/movebugs.pl172
-rwxr-xr-xcontrib/reorg-tools/movecomponent.pl193
-rwxr-xr-xcontrib/reorg-tools/reset_default_user.pl143
-rwxr-xr-xcontrib/reorg-tools/syncflags.pl86
-rwxr-xr-xcontrib/reorg-tools/syncmsandversions.pl121
-rwxr-xr-xcontrib/sanitizeme.pl195
-rwxr-xr-xcontrib/verify-user.pl129
-rwxr-xr-xdescribecomponents.cgi7
-rwxr-xr-xdescribekeywords.cgi12
-rw-r--r--docs/en/xml/using.xml9
-rwxr-xr-xeditusers.cgi16
-rwxr-xr-xenter_bug.cgi249
-rw-r--r--errors/401.html40
-rw-r--r--errors/403.html37
-rw-r--r--errors/404.html37
-rw-r--r--errors/500.html37
-rw-r--r--extensions/BMO/Config.pm38
-rw-r--r--extensions/BMO/Extension.pm1136
-rw-r--r--extensions/BMO/lib/Constants.pm33
-rw-r--r--extensions/BMO/lib/Data.pm467
-rw-r--r--extensions/BMO/lib/FakeBug.pm42
-rw-r--r--extensions/BMO/lib/Reports.pm1191
-rw-r--r--extensions/BMO/lib/WebService.pm208
-rw-r--r--extensions/BMO/template/en/default/account/create.html.tmpl184
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-bootgecko-partner.txt.tmpl23
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl33
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-doc.txt.tmpl20
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl57
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-finance.txt.tmpl35
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-ipp.txt.tmpl30
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl39
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-mdn.txt.tmpl66
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl44
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-privacy-data.txt.tmpl30
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl28
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl50
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-bootgecko-partner.html.tmpl240
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl326
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-doc.html.tmpl220
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl288
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-finance.html.tmpl257
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-ipp.html.tmpl163
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl230
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl226
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mdn.html.tmpl277
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl177
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl648
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl87
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl219
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-privacy-data.html.tmpl219
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl70
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl751
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl87
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl800
-rw-r--r--extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl38
-rw-r--r--extensions/BMO/template/en/default/bug/create/user-message.html.tmpl54
-rw-r--r--extensions/BMO/template/en/default/email/bugmail.html.tmpl223
-rw-r--r--extensions/BMO/template/en/default/email/bugmail.txt.tmpl93
-rw-r--r--extensions/BMO/template/en/default/global/choose-product.html.tmpl228
-rw-r--r--extensions/BMO/template/en/default/global/common-links.html.tmpl124
-rw-r--r--extensions/BMO/template/en/default/global/header.html.tmpl416
-rw-r--r--extensions/BMO/template/en/default/global/prod-comp-search.html.tmpl43
-rw-r--r--extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl1
-rw-r--r--extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl19
-rw-r--r--extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl42
-rw-r--r--extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl13
-rw-r--r--extensions/BMO/template/en/default/hook/bug/comments-end.html.tmpl20
-rw-r--r--extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl40
-rw-r--r--extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl22
-rw-r--r--extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl128
-rw-r--r--extensions/BMO/template/en/default/hook/bug/edit-after_importance.html.tmpl77
-rw-r--r--extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl96
-rw-r--r--extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl9
-rw-r--r--extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl18
-rw-r--r--extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl12
-rw-r--r--extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl1
-rw-r--r--extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl67
-rw-r--r--extensions/BMO/template/en/default/hook/global/header-start.html.tmpl40
-rw-r--r--extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl5
-rw-r--r--extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl5
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl5
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error-error_message.html.tmpl15
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl36
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl29
-rw-r--r--extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl3
-rw-r--r--extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl15
-rw-r--r--extensions/BMO/template/en/default/hook/index-intro.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/hook/pages/fields-open-status.html.tmpl11
-rw-r--r--extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl13
-rw-r--r--extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl52
-rw-r--r--extensions/BMO/template/en/default/list/list.microsummary.tmpl (renamed from template/en/default/global/help.html.tmpl)20
-rw-r--r--extensions/BMO/template/en/default/list/server-push.html.tmpl52
-rw-r--r--extensions/BMO/template/en/default/pages/bug-writing.html.tmpl25
-rw-r--r--extensions/BMO/template/en/default/pages/email_queue.html.tmpl66
-rw-r--r--extensions/BMO/template/en/default/pages/etiquette.html.tmpl146
-rw-r--r--extensions/BMO/template/en/default/pages/get_help.html.tmpl42
-rw-r--r--extensions/BMO/template/en/default/pages/get_permissions.html.tmpl44
-rw-r--r--extensions/BMO/template/en/default/pages/group_admins.html.tmpl54
-rw-r--r--extensions/BMO/template/en/default/pages/group_members.html.tmpl97
-rw-r--r--extensions/BMO/template/en/default/pages/group_members.json.tmpl32
-rw-r--r--extensions/BMO/template/en/default/pages/group_membership.html.tmpl75
-rw-r--r--extensions/BMO/template/en/default/pages/group_membership.txt.tmpl16
-rw-r--r--extensions/BMO/template/en/default/pages/query_database.html.tmpl47
-rw-r--r--extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl103
-rw-r--r--extensions/BMO/template/en/default/pages/researchers.html.tmpl21
-rw-r--r--extensions/BMO/template/en/default/pages/triage_reports.html.tmpl199
-rw-r--r--extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl304
-rw-r--r--extensions/BMO/template/en/default/pages/user_activity.html.tmpl226
-rw-r--r--extensions/BMO/template/en/default/search/search-plugin.xml.tmpl17
-rw-r--r--extensions/BMO/web/core.pngbin0 -> 7497 bytes
-rw-r--r--extensions/BMO/web/images/advanced.pngbin0 -> 720 bytes
-rw-r--r--extensions/BMO/web/images/background.pngbin0 -> 1695 bytes
-rw-r--r--extensions/BMO/web/images/bugzilla.pngbin0 -> 1242 bytes
-rw-r--r--extensions/BMO/web/images/favicon.icobin0 -> 1150 bytes
-rw-r--r--extensions/BMO/web/images/groups/bugzilla-approvers.pngbin0 -> 829 bytes
-rw-r--r--extensions/BMO/web/images/groups/calendar-drivers.pngbin0 -> 744 bytes
-rw-r--r--extensions/BMO/web/images/guided.pngbin0 -> 1045 bytes
-rw-r--r--extensions/BMO/web/images/mozchomp.gifbin0 -> 89485 bytes
-rw-r--r--extensions/BMO/web/images/mozilla-tab.pngbin0 -> 7535 bytes
-rw-r--r--extensions/BMO/web/images/presshat.pngbin0 -> 23450 bytes
-rw-r--r--extensions/BMO/web/images/sign_warning.pngbin0 -> 1776 bytes
-rw-r--r--extensions/BMO/web/images/stop-sign.gifbin0 -> 3227 bytes
-rw-r--r--extensions/BMO/web/images/throbber.gifbin0 -> 723 bytes
-rw-r--r--extensions/BMO/web/js/edit_bug.js91
-rw-r--r--extensions/BMO/web/js/edituser_menu.js33
-rw-r--r--extensions/BMO/web/js/form_validate.js21
-rw-r--r--extensions/BMO/web/js/release_tracking_report.js203
-rw-r--r--extensions/BMO/web/js/sorttable.js709
-rw-r--r--extensions/BMO/web/js/swag.js60
-rw-r--r--extensions/BMO/web/js/triage_reports.js83
-rw-r--r--extensions/BMO/web/js/webtrends.js213
-rw-r--r--extensions/BMO/web/producticons/camino.pngbin0 -> 6060 bytes
-rw-r--r--extensions/BMO/web/producticons/dino.pngbin0 -> 3375 bytes
-rw-r--r--extensions/BMO/web/producticons/fennec.pngbin0 -> 9023 bytes
-rw-r--r--extensions/BMO/web/producticons/firefox.pngbin0 -> 9395 bytes
-rw-r--r--extensions/BMO/web/producticons/idea.pngbin0 -> 6189 bytes
-rw-r--r--extensions/BMO/web/producticons/input.pngbin0 -> 8333 bytes
-rw-r--r--extensions/BMO/web/producticons/labs.pngbin0 -> 4085 bytes
-rw-r--r--extensions/BMO/web/producticons/marketplace.pngbin0 -> 7412 bytes
-rw-r--r--extensions/BMO/web/producticons/mozilla.pngbin0 -> 10808 bytes
-rw-r--r--extensions/BMO/web/producticons/other.pngbin0 -> 6654 bytes
-rw-r--r--extensions/BMO/web/producticons/seamonkey.pngbin0 -> 5255 bytes
-rw-r--r--extensions/BMO/web/producticons/sunbird.pngbin0 -> 10462 bytes
-rw-r--r--extensions/BMO/web/producticons/thunderbird.pngbin0 -> 9939 bytes
-rw-r--r--extensions/BMO/web/styles/choose_product.css16
-rw-r--r--extensions/BMO/web/styles/create_account.css62
-rw-r--r--extensions/BMO/web/styles/edit_bug.css49
-rw-r--r--extensions/BMO/web/styles/reports.css66
-rw-r--r--extensions/BMO/web/styles/triage_reports.css23
-rw-r--r--extensions/BMO/web/yui-history-iframe.txt (renamed from extensions/BmpConvert/disabled)0
-rw-r--r--extensions/BzAPI/Config.pm63
-rw-r--r--extensions/BzAPI/Extension.pm71
-rw-r--r--extensions/BzAPI/template/en/default/config.json.tmpl315
-rw-r--r--extensions/ComponentWatching/Config.pm12
-rw-r--r--extensions/ComponentWatching/Extension.pm498
-rw-r--r--extensions/ComponentWatching/template/en/default/account/prefs/component_watch.html.tmpl232
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/account/prefs/email-relationships.html.tmpl10
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl14
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/admin/components/edit-common-rows.html.tmpl20
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/admin/components/list-before_table.html.tmpl17
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/global/messages-component_updated_fields.html.tmpl15
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/global/reason-descs-end.none.tmpl10
-rw-r--r--extensions/ComponentWatching/template/en/default/hook/global/user-error-errors.html.tmpl17
-rw-r--r--extensions/ContributorEngagement/Config.pm19
-rw-r--r--extensions/ContributorEngagement/Extension.pm134
-rw-r--r--extensions/ContributorEngagement/lib/Constants.pm36
-rw-r--r--extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl46
-rw-r--r--extensions/Example/Extension.pm152
-rw-r--r--extensions/FlagDefaultRequestee/Config.pm17
-rw-r--r--extensions/FlagDefaultRequestee/Extension.pm144
-rw-r--r--extensions/FlagDefaultRequestee/lib/Constants.pm25
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/flag/default_requestees.html.tmpl105
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl21
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/hook/attachment/create-end.html.tmpl9
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/hook/attachment/edit-end.html.tmpl9
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/hook/bug/create/create-form.html.tmpl9
-rw-r--r--extensions/FlagDefaultRequestee/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl9
-rw-r--r--extensions/FlagTypeComment/Config.pm29
-rw-r--r--extensions/FlagTypeComment/Extension.pm200
-rw-r--r--extensions/FlagTypeComment/lib/Constants.pm50
-rw-r--r--extensions/FlagTypeComment/template/en/default/flag/type_comment.html.tmpl54
-rw-r--r--extensions/FlagTypeComment/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl45
-rw-r--r--extensions/FlagTypeComment/template/en/default/hook/attachment/create-end.html.tmpl23
-rw-r--r--extensions/FlagTypeComment/template/en/default/hook/attachment/edit-end.html.tmpl23
-rw-r--r--extensions/FlagTypeComment/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl23
-rw-r--r--extensions/GuidedBugEntry/Config.pm19
-rw-r--r--extensions/GuidedBugEntry/Extension.pm116
-rw-r--r--extensions/GuidedBugEntry/template/en/default/bug/create/comment-guided.txt.tmpl25
-rw-r--r--extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl529
-rw-r--r--extensions/GuidedBugEntry/template/en/default/guided/products.html.tmpl51
-rw-r--r--extensions/GuidedBugEntry/template/en/default/pages/guided_products.js.tmpl26
-rw-r--r--extensions/GuidedBugEntry/web/images/advanced.pngbin0 -> 720 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/help.pngbin0 -> 786 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/input.pngbin0 -> 5545 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/message.pngbin0 -> 1497 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/camino.pngbin0 -> 6060 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/core.pngbin0 -> 7497 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/dino.pngbin0 -> 3375 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/fennec.pngbin0 -> 9023 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/firefox.pngbin0 -> 9395 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/labs.pngbin0 -> 4085 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/marketplace.pngbin0 -> 7412 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/mozilla.pngbin0 -> 10808 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/other.pngbin0 -> 6654 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/seamonkey.pngbin0 -> 5255 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/sunbird.pngbin0 -> 10462 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/products/thunderbird.pngbin0 -> 9939 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/sumo.pngbin0 -> 3517 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/support.pngbin0 -> 2409 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/throbber.gifbin0 -> 723 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/warning.pngbin0 -> 1428 bytes
-rw-r--r--extensions/GuidedBugEntry/web/images/webbug.pngbin0 -> 2053 bytes
-rw-r--r--extensions/GuidedBugEntry/web/js/guided.js924
-rw-r--r--extensions/GuidedBugEntry/web/js/products.js118
-rw-r--r--extensions/GuidedBugEntry/web/style/guided.css237
-rw-r--r--extensions/GuidedBugEntry/web/yui-history-iframe.txt (renamed from extensions/Voting/disabled)0
-rw-r--r--extensions/InlineHistory/Config.pm13
-rw-r--r--extensions/InlineHistory/Extension.pm206
-rw-r--r--extensions/InlineHistory/README10
-rw-r--r--extensions/InlineHistory/template/en/default/hook/bug/comments-aftercomments.html.tmpl152
-rw-r--r--extensions/InlineHistory/template/en/default/hook/bug/comments-comment_banner.html.tmpl13
-rw-r--r--extensions/InlineHistory/template/en/default/hook/bug/show-header-end.html.tmpl12
-rw-r--r--extensions/InlineHistory/template/en/default/hook/global/setting-descs-settings.none.tmpl11
-rw-r--r--extensions/InlineHistory/web/inline-history.js385
-rw-r--r--extensions/InlineHistory/web/style.css35
-rw-r--r--extensions/LastResolved/Config.pm20
-rw-r--r--extensions/LastResolved/Extension.pm112
-rw-r--r--extensions/LastResolved/template/en/default/hook/global/field-descs-end.none.tmpl11
-rw-r--r--extensions/LimitedEmail/Config.pm22
-rw-r--r--extensions/LimitedEmail/Extension.pm62
-rw-r--r--extensions/LimitedEmail/disabled0
-rw-r--r--extensions/MozProjectReview/Config.pm19
-rw-r--r--extensions/MozProjectReview/Extension.pm305
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-data-safety.txt.tmpl40
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-finance.txt.tmpl31
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-legal.txt.tmpl50
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-policy.txt.tmpl18
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-tech.txt.tmpl12
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-vendor.txt.tmpl16
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-sec-review.txt.tmpl20
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review.txt.tmpl36
-rw-r--r--extensions/MozProjectReview/template/en/default/bug/create/create-moz-project-review.html.tmpl915
-rw-r--r--extensions/MozProjectReview/template/en/default/hook/global/messages-messages.html.tmpl13
-rw-r--r--extensions/MozProjectReview/web/js/moz_project_review.js307
-rw-r--r--extensions/MozProjectReview/web/style/moz_project_review.css48
-rw-r--r--extensions/MyDashboard/Config.pm14
-rw-r--r--extensions/MyDashboard/Extension.pm126
-rw-r--r--extensions/MyDashboard/lib/Queries.pm259
-rw-r--r--extensions/MyDashboard/lib/TimeAgo.pm179
-rw-r--r--extensions/MyDashboard/lib/Util.pm50
-rw-r--r--extensions/MyDashboard/lib/WebService.pm111
-rw-r--r--extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-header.html.tmpl11
-rw-r--r--extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-row.html.tmpl15
-rw-r--r--extensions/MyDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl12
-rw-r--r--extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl150
-rw-r--r--extensions/MyDashboard/web/js/flags.js189
-rw-r--r--extensions/MyDashboard/web/js/query.js167
-rw-r--r--extensions/MyDashboard/web/styles/mydashboard.css73
-rw-r--r--extensions/Needinfo/Config.pm18
-rw-r--r--extensions/Needinfo/Extension.pm162
-rw-r--r--extensions/Needinfo/template/en/default/bug/needinfo.html.tmpl97
-rw-r--r--extensions/Needinfo/template/en/default/hook/attachment/create-form_before_submit.html.tmpl17
-rw-r--r--extensions/Needinfo/template/en/default/hook/attachment/edit-after_comment_textarea.html.tmpl12
-rw-r--r--extensions/Needinfo/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl11
-rw-r--r--extensions/Needinfo/template/en/default/hook/request/email-after_summary.txt.tmpl13
-rw-r--r--extensions/OpenGraph/Config.pm16
-rw-r--r--extensions/OpenGraph/Extension.pm16
-rw-r--r--extensions/OpenGraph/template/en/default/hook/global/header-start.html.tmpl13
-rw-r--r--extensions/OpenGraph/web/bugzilla.pngbin0 -> 17036 bytes
-rw-r--r--extensions/OrangeFactor/Config.pm13
-rw-r--r--extensions/OrangeFactor/Extension.pm44
-rw-r--r--extensions/OrangeFactor/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl26
-rw-r--r--extensions/OrangeFactor/template/en/default/hook/bug/show-header-end.html.tmpl17
-rw-r--r--extensions/OrangeFactor/template/en/default/hook/global/setting-descs-settings.none.tmpl11
-rw-r--r--extensions/OrangeFactor/web/js/AUTHORS.processing.js35
-rw-r--r--extensions/OrangeFactor/web/js/LICENSE.processing.js22
-rw-r--r--extensions/OrangeFactor/web/js/LICENSE.sparklines.js20
-rw-r--r--extensions/OrangeFactor/web/js/orange_factor.js91
-rw-r--r--extensions/OrangeFactor/web/js/sparklines.min.js133
-rw-r--r--extensions/OrangeFactor/web/style/orangefactor.css13
-rw-r--r--extensions/Persona/Config.pm29
-rw-r--r--extensions/Persona/Extension.pm73
-rw-r--r--extensions/Persona/TODO19
-rw-r--r--extensions/Persona/lib/Config.pm36
-rw-r--r--extensions/Persona/lib/Login.pm124
-rw-r--r--extensions/Persona/template/en/default/admin/params/browserid.html.tmpl22
-rw-r--r--extensions/Persona/template/en/default/admin/params/persona.html.tmpl22
-rw-r--r--extensions/Persona/template/en/default/hook/account/auth/login-additional_methods.html.tmpl6
-rw-r--r--extensions/Persona/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl17
-rw-r--r--extensions/Persona/template/en/default/hook/account/create-additional_methods.html.tmpl18
-rw-r--r--extensions/Persona/template/en/default/hook/global/header-additional_header.html.tmpl84
-rw-r--r--extensions/Persona/template/en/default/hook/global/user-error-errors.html.tmpl12
-rw-r--r--extensions/Persona/web/images/persona_sign_in.pngbin0 -> 3684 bytes
-rw-r--r--extensions/Persona/web/images/sign_in.pngbin0 -> 1993 bytes
-rw-r--r--extensions/ProdCompSearch/Config.pm15
-rw-r--r--extensions/ProdCompSearch/Extension.pm21
-rw-r--r--extensions/ProdCompSearch/lib/WebService.pm100
-rw-r--r--extensions/ProdCompSearch/template/en/default/pages/prodcompsearch.html.tmpl25
-rw-r--r--extensions/ProdCompSearch/template/en/default/prodcompsearch/form.html.tmpl34
-rw-r--r--extensions/ProdCompSearch/web/images/throbber.gifbin0 -> 723 bytes
-rw-r--r--extensions/ProdCompSearch/web/js/prod_comp_search.js126
-rw-r--r--extensions/ProdCompSearch/web/styles/prod_comp_search.css20
-rw-r--r--extensions/ProductDashboard/Config.pm14
-rw-r--r--extensions/ProductDashboard/Extension.pm200
-rw-r--r--extensions/ProductDashboard/lib/Queries.pm475
-rw-r--r--extensions/ProductDashboard/lib/Util.pm95
-rw-r--r--extensions/ProductDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl9
-rw-r--r--extensions/ProductDashboard/template/en/default/hook/global/user-error-errors.html.tmpl12
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard.html.tmpl237
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/components.html.tmpl146
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/duplicates.html.tmpl34
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/popularity.html.tmpl38
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/recents.html.tmpl87
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/roadmap.html.tmpl27
-rw-r--r--extensions/ProductDashboard/template/en/default/pages/productdashboard/summary.html.tmpl122
-rw-r--r--extensions/ProductDashboard/web/images/spacer.gifbin0 -> 43 bytes
-rw-r--r--extensions/ProductDashboard/web/js/components.js75
-rw-r--r--extensions/ProductDashboard/web/js/duplicates.js28
-rw-r--r--extensions/ProductDashboard/web/js/popularity.js28
-rw-r--r--extensions/ProductDashboard/web/js/recents.js32
-rw-r--r--extensions/ProductDashboard/web/js/roadmap.js24
-rw-r--r--extensions/ProductDashboard/web/js/summary.js45
-rw-r--r--extensions/ProductDashboard/web/styles/productdashboard.css45
-rw-r--r--extensions/Profanivore/Config.pm40
-rw-r--r--extensions/Profanivore/Extension.pm169
-rw-r--r--extensions/Profanivore/README14
-rw-r--r--extensions/Push/Config.pm61
-rw-r--r--extensions/Push/Extension.pm645
-rwxr-xr-xextensions/Push/bin/bugzilla-pushd.pl54
-rwxr-xr-xextensions/Push/bin/nagios_push_checker.pl54
-rw-r--r--extensions/Push/lib/Admin.pm122
-rw-r--r--extensions/Push/lib/BacklogMessage.pm149
-rw-r--r--extensions/Push/lib/BacklogQueue.pm127
-rw-r--r--extensions/Push/lib/Backoff.pm109
-rw-r--r--extensions/Push/lib/Config.pm215
-rw-r--r--extensions/Push/lib/Connector.disabled/ServiceNow.pm434
-rw-r--r--extensions/Push/lib/Connector/AMQP.pm230
-rw-r--r--extensions/Push/lib/Connector/Base.pm106
-rw-r--r--extensions/Push/lib/Connector/File.pm68
-rw-r--r--extensions/Push/lib/Connector/TCL.pm349
-rw-r--r--extensions/Push/lib/Connectors.pm116
-rw-r--r--extensions/Push/lib/Constants.pm41
-rw-r--r--extensions/Push/lib/Daemon.pm96
-rw-r--r--extensions/Push/lib/Log.pm45
-rw-r--r--extensions/Push/lib/LogEntry.pm70
-rw-r--r--extensions/Push/lib/Logger.pm70
-rw-r--r--extensions/Push/lib/Message.pm103
-rw-r--r--extensions/Push/lib/Option.pm66
-rw-r--r--extensions/Push/lib/Push.pm264
-rw-r--r--extensions/Push/lib/Queue.pm72
-rw-r--r--extensions/Push/lib/Serialise.pm322
-rw-r--r--extensions/Push/lib/Util.pm162
-rw-r--r--extensions/Push/template/en/default/hook/admin/admin-end_links_right.html.tmpl18
-rw-r--r--extensions/Push/template/en/default/hook/global/code-error-errors.html.tmpl25
-rw-r--r--extensions/Push/template/en/default/hook/global/messages-messages.html.tmpl16
-rw-r--r--extensions/Push/template/en/default/hook/global/user-error-errors.html.tmpl11
-rw-r--r--extensions/Push/template/en/default/pages/push_config.html.tmpl134
-rw-r--r--extensions/Push/template/en/default/pages/push_log.html.tmpl45
-rw-r--r--extensions/Push/template/en/default/pages/push_queues.html.tmpl102
-rw-r--r--extensions/Push/template/en/default/pages/push_queues_view.html.tmpl80
-rw-r--r--extensions/Push/template/en/default/setup/strings.txt.pl11
-rw-r--r--extensions/Push/web/admin.css71
-rw-r--r--extensions/Push/web/admin.js37
-rw-r--r--extensions/REMO/Config.pm34
-rw-r--r--extensions/REMO/Extension.pm230
-rw-r--r--extensions/REMO/template/en/default/bug/create/comment-mozreps.txt.tmpl95
-rw-r--r--extensions/REMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl55
-rw-r--r--extensions/REMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl71
-rw-r--r--extensions/REMO/template/en/default/bug/create/create-mozreps.html.tmpl241
-rw-r--r--extensions/REMO/template/en/default/bug/create/create-remo-budget.html.tmpl249
-rw-r--r--extensions/REMO/template/en/default/bug/create/create-remo-swag.html.tmpl293
-rw-r--r--extensions/REMO/template/en/default/bug/create/create-remo-swag.xml.tmpl104
-rw-r--r--extensions/REMO/template/en/default/bug/create/created-mozreps.html.tmpl38
-rw-r--r--extensions/REMO/template/en/default/bug/create/created-remo-budget.html.tmpl27
-rw-r--r--extensions/REMO/template/en/default/hook/global/user-error-errors.html.tmpl40
-rw-r--r--extensions/REMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl37
-rw-r--r--extensions/REMO/template/en/default/pages/remo-form-payment.html.tmpl243
-rw-r--r--extensions/REMO/web/js/form_validate.js21
-rw-r--r--extensions/REMO/web/js/swag.js60
-rw-r--r--extensions/REMO/web/styles/moz_reps.css44
-rw-r--r--extensions/RequestWhiner/Config.pm33
-rw-r--r--extensions/RequestWhiner/Extension.pm43
-rwxr-xr-xextensions/RequestWhiner/bin/whineatrequests.pl155
-rw-r--r--extensions/RequestWhiner/lib/Constants.pm31
-rw-r--r--extensions/RequestWhiner/template/en/default/requestwhiner/header.txt.tmpl6
-rw-r--r--extensions/RequestWhiner/template/en/default/requestwhiner/mail.html.tmpl62
-rw-r--r--extensions/RequestWhiner/template/en/default/requestwhiner/mail.txt.tmpl41
-rw-r--r--extensions/RestrictComments/Config.pm16
-rw-r--r--extensions/RestrictComments/Extension.pm95
-rw-r--r--extensions/RestrictComments/lib/Config.pm47
-rw-r--r--extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl23
-rw-r--r--extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl26
-rw-r--r--extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl62
-rw-r--r--extensions/SecureMail/Config.pm47
-rw-r--r--extensions/SecureMail/Extension.pm627
-rw-r--r--extensions/SecureMail/README8
-rw-r--r--extensions/SecureMail/template/en/default/account/email/encryption-required.txt.tmpl15
-rw-r--r--extensions/SecureMail/template/en/default/account/email/securemail-test.txt.tmpl23
-rw-r--r--extensions/SecureMail/template/en/default/account/prefs/securemail.html.tmpl40
-rw-r--r--extensions/SecureMail/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl28
-rw-r--r--extensions/SecureMail/template/en/default/hook/admin/groups/create-field.html.tmpl25
-rw-r--r--extensions/SecureMail/template/en/default/hook/admin/groups/edit-field.html.tmpl27
-rw-r--r--extensions/SecureMail/template/en/default/hook/global/user-error-errors.html.tmpl27
-rw-r--r--extensions/SecureMail/template/en/default/pages/securemail/help.html.tmpl98
-rw-r--r--extensions/ShadowBugs/Config.pm15
-rw-r--r--extensions/ShadowBugs/Extension.pm99
-rw-r--r--extensions/ShadowBugs/disabled0
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/bug/comments-aftercomments.html.tmpl70
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/bug/edit-after_comment_textarea.html.tmpl13
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl27
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/bug/edit-custom_field.html.tmpl9
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/bug/show-header-end.html.tmpl12
-rw-r--r--extensions/ShadowBugs/template/en/default/hook/global/user-error-errors.html.tmpl14
-rw-r--r--extensions/ShadowBugs/web/shadow-bugs.js51
-rw-r--r--extensions/ShadowBugs/web/style.css10
-rw-r--r--extensions/SiteMapIndex/Config.pm36
-rw-r--r--extensions/SiteMapIndex/Extension.pm157
-rw-r--r--extensions/SiteMapIndex/lib/Constants.pm47
-rw-r--r--extensions/SiteMapIndex/lib/Util.pm205
-rw-r--r--extensions/SiteMapIndex/robots.txt10
-rw-r--r--extensions/SiteMapIndex/template/en/default/hook/global/header-additional_header.html.tmpl23
-rw-r--r--extensions/SiteMapIndex/template/en/default/hook/global/messages-messages.html.tmpl37
-rw-r--r--extensions/Splinter/Config.pm5
-rw-r--r--extensions/Splinter/Extension.pm146
-rw-r--r--extensions/Splinter/lib/Config.pm46
-rw-r--r--extensions/Splinter/lib/Util.pm160
-rw-r--r--extensions/Splinter/template/en/default/admin/params/splinter.html.tmpl38
-rw-r--r--extensions/Splinter/template/en/default/hook/attachment/edit-action.html.tmpl25
-rw-r--r--extensions/Splinter/template/en/default/hook/attachment/list-action.html.tmpl25
-rw-r--r--extensions/Splinter/template/en/default/hook/global/user-error-errors.html.tmpl5
-rw-r--r--extensions/Splinter/template/en/default/hook/request/email-after_summary.txt.tmpl7
-rw-r--r--extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl4
-rw-r--r--extensions/Splinter/template/en/default/pages/splinter.html.tmpl270
-rw-r--r--extensions/Splinter/template/en/default/pages/splinter/help.html.tmpl153
-rw-r--r--extensions/Splinter/web/splinter.css419
-rw-r--r--extensions/Splinter/web/splinter.js2572
-rw-r--r--extensions/TagNewUsers/Config.pm15
-rw-r--r--extensions/TagNewUsers/Extension.pm258
-rw-r--r--extensions/TagNewUsers/template/en/default/hook/bug/comments-user.html.tmpl26
-rw-r--r--extensions/TagNewUsers/template/en/default/hook/bug/show-header-end.html.tmpl9
-rw-r--r--extensions/TagNewUsers/web/style.css10
-rw-r--r--extensions/TryAutoLand/Config.pm19
-rw-r--r--extensions/TryAutoLand/Extension.pm323
-rwxr-xr-xextensions/TryAutoLand/bin/TryAutoLand.getBugs.pl60
-rwxr-xr-xextensions/TryAutoLand/bin/TryAutoLand.updateStatus.pl65
-rwxr-xr-xextensions/TryAutoLand/bin/TryAutoLand.updateStatus_json.pl65
-rw-r--r--extensions/TryAutoLand/lib/Constants.pm31
-rw-r--r--extensions/TryAutoLand/lib/WebService.pm189
-rw-r--r--extensions/TryAutoLand/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl101
-rw-r--r--extensions/TryAutoLand/template/en/default/hook/bug/field-help-end.none.tmpl15
-rw-r--r--extensions/TryAutoLand/template/en/default/hook/bug/show-header-end.html.tmpl11
-rw-r--r--extensions/TryAutoLand/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl11
-rw-r--r--extensions/TryAutoLand/template/en/default/hook/global/user-error-errors.html.tmpl33
-rw-r--r--extensions/TryAutoLand/web/style.css23
-rw-r--r--extensions/TypeSniffer/Config.pm40
-rw-r--r--extensions/TypeSniffer/Extension.pm76
-rw-r--r--extensions/Voting/Extension.pm13
-rw-r--r--extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl3
-rw-r--r--extensions/Voting/template/en/default/pages/voting/user.html.tmpl2
-rw-r--r--images/buggie.pngbin0 -> 17002 bytes
-rwxr-xr-ximportxml.pl2
-rwxr-xr-xjobqueue.pl1
-rw-r--r--js/TUI.js10
-rw-r--r--js/attachment.js10
-rw-r--r--js/comments.js27
-rw-r--r--js/create_bug.js116
-rw-r--r--js/custom-search.js174
-rw-r--r--js/field.js78
-rw-r--r--js/instant-search.js201
-rw-r--r--js/util.js49
-rw-r--r--js/yui3/align-plugin/align-plugin-min.js7
-rw-r--r--js/yui3/anim-base/anim-base-min.js7
-rw-r--r--js/yui3/anim-color/anim-color-min.js7
-rw-r--r--js/yui3/anim-curve/anim-curve-min.js7
-rw-r--r--js/yui3/anim-easing/anim-easing-min.js7
-rw-r--r--js/yui3/anim-node-plugin/anim-node-plugin-min.js7
-rw-r--r--js/yui3/anim-scroll/anim-scroll-min.js7
-rw-r--r--js/yui3/anim-shape/anim-shape-min.js7
-rw-r--r--js/yui3/anim-xy/anim-xy-min.js7
-rw-r--r--js/yui3/app-base/app-base-min.js7
-rw-r--r--js/yui3/app-content/app-content-min.js7
-rw-r--r--js/yui3/app-transitions-css/app-transitions-css-min.css7
-rw-r--r--js/yui3/app-transitions-css/app-transitions-css.css29
-rw-r--r--js/yui3/app-transitions-native/app-transitions-native-min.js7
-rw-r--r--js/yui3/app-transitions/app-transitions-min.js7
-rw-r--r--js/yui3/array-extras/array-extras-min.js7
-rw-r--r--js/yui3/array-invoke/array-invoke-min.js7
-rw-r--r--js/yui3/arraylist-add/arraylist-add-min.js7
-rw-r--r--js/yui3/arraylist-filter/arraylist-filter-min.js7
-rw-r--r--js/yui3/arraylist/arraylist-min.js7
-rw-r--r--js/yui3/arraysort/arraysort-min.js7
-rw-r--r--js/yui3/assets/skins/sam/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/assets/skins/sam/autocomplete-list.css7
-rw-r--r--js/yui3/assets/skins/sam/bg.pngbin0 -> 121 bytes
-rw-r--r--js/yui3/assets/skins/sam/calendar-base.css7
-rw-r--r--js/yui3/assets/skins/sam/calendar.css7
-rw-r--r--js/yui3/assets/skins/sam/calendarnavigator.css7
-rw-r--r--js/yui3/assets/skins/sam/console-filters.css7
-rw-r--r--js/yui3/assets/skins/sam/console.css7
-rw-r--r--js/yui3/assets/skins/sam/datatable-base-deprecated.css8
-rw-r--r--js/yui3/assets/skins/sam/datatable-base.css7
-rw-r--r--js/yui3/assets/skins/sam/datatable-message.css7
-rw-r--r--js/yui3/assets/skins/sam/datatable-scroll.css7
-rw-r--r--js/yui3/assets/skins/sam/datatable-sort.css7
-rw-r--r--js/yui3/assets/skins/sam/dial.css7
-rw-r--r--js/yui3/assets/skins/sam/dt-arrow-dn.pngbin0 -> 101 bytes
-rw-r--r--js/yui3/assets/skins/sam/dt-arrow-up.pngbin0 -> 99 bytes
-rw-r--r--js/yui3/assets/skins/sam/horizontal-menu-submenu-indicator.pngbin0 -> 157 bytes
-rw-r--r--js/yui3/assets/skins/sam/horizontal-menu-submenu-toggle.pngbin0 -> 183 bytes
-rw-r--r--js/yui3/assets/skins/sam/node-flick.css7
-rw-r--r--js/yui3/assets/skins/sam/node-menunav.css7
-rw-r--r--js/yui3/assets/skins/sam/overlay.css7
-rw-r--r--js/yui3/assets/skins/sam/panel.css7
-rw-r--r--js/yui3/assets/skins/sam/rail-x-lines.pngbin0 -> 3656 bytes
-rw-r--r--js/yui3/assets/skins/sam/rail-x.pngbin0 -> 3639 bytes
-rw-r--r--js/yui3/assets/skins/sam/rail-y-lines.pngbin0 -> 3642 bytes
-rw-r--r--js/yui3/assets/skins/sam/rail-y.pngbin0 -> 3629 bytes
-rw-r--r--js/yui3/assets/skins/sam/resize-base.css7
-rw-r--r--js/yui3/assets/skins/sam/scrollview-base.css7
-rw-r--r--js/yui3/assets/skins/sam/scrollview-list.css7
-rw-r--r--js/yui3/assets/skins/sam/scrollview-scrollbars.css7
-rw-r--r--js/yui3/assets/skins/sam/skin.css34
-rw-r--r--js/yui3/assets/skins/sam/slider-base.css7
-rw-r--r--js/yui3/assets/skins/sam/sort-arrow-sprite-ie.pngbin0 -> 3628 bytes
-rw-r--r--js/yui3/assets/skins/sam/sort-arrow-sprite.pngbin0 -> 2884 bytes
-rw-r--r--js/yui3/assets/skins/sam/sprite.pngbin0 -> 2913 bytes
-rw-r--r--js/yui3/assets/skins/sam/sprite_icons.gifbin0 -> 142 bytes
-rw-r--r--js/yui3/assets/skins/sam/sprite_icons.pngbin0 -> 176 bytes
-rw-r--r--js/yui3/assets/skins/sam/tabview.css7
-rw-r--r--js/yui3/assets/skins/sam/test-console.css7
-rw-r--r--js/yui3/assets/skins/sam/thumb-x.pngbin0 -> 3873 bytes
-rw-r--r--js/yui3/assets/skins/sam/thumb-y.pngbin0 -> 3860 bytes
-rw-r--r--js/yui3/assets/skins/sam/vertical-menu-submenu-indicator.pngbin0 -> 156 bytes
-rw-r--r--js/yui3/assets/skins/sam/warn_error.pngbin0 -> 571 bytes
-rw-r--r--js/yui3/assets/skins/sam/widget-base.css7
-rw-r--r--js/yui3/assets/skins/sam/widget-buttons.css7
-rw-r--r--js/yui3/assets/skins/sam/widget-modality.css7
-rw-r--r--js/yui3/assets/skins/sam/widget-stack.css7
-rw-r--r--js/yui3/async-queue/async-queue-min.js7
-rw-r--r--js/yui3/attribute-base/attribute-base-min.js7
-rw-r--r--js/yui3/attribute-complex/attribute-complex-min.js7
-rw-r--r--js/yui3/attribute-core/attribute-core-min.js7
-rw-r--r--js/yui3/attribute-events/attribute-events-min.js7
-rw-r--r--js/yui3/attribute-extras/attribute-extras-min.js7
-rw-r--r--js/yui3/autocomplete-base/autocomplete-base-min.js7
-rw-r--r--js/yui3/autocomplete-filters-accentfold/autocomplete-filters-accentfold-min.js7
-rw-r--r--js/yui3/autocomplete-filters/autocomplete-filters-min.js7
-rw-r--r--js/yui3/autocomplete-highlighters-accentfold/autocomplete-highlighters-accentfold-min.js7
-rw-r--r--js/yui3/autocomplete-highlighters/autocomplete-highlighters-min.js7
-rw-r--r--js/yui3/autocomplete-list-keys/autocomplete-list-keys-min.js7
-rw-r--r--js/yui3/autocomplete-list/assets/autocomplete-list-core.css33
-rw-r--r--js/yui3/autocomplete-list/assets/skins/night/autocomplete-list.css7
-rw-r--r--js/yui3/autocomplete-list/assets/skins/sam/autocomplete-list.css7
-rw-r--r--js/yui3/autocomplete-list/autocomplete-list-min.js7
-rw-r--r--js/yui3/autocomplete-list/lang/autocomplete-list.js7
-rw-r--r--js/yui3/autocomplete-list/lang/autocomplete-list_en.js7
-rw-r--r--js/yui3/autocomplete-plugin/autocomplete-plugin-min.js7
-rw-r--r--js/yui3/autocomplete-sources/autocomplete-sources-min.js7
-rw-r--r--js/yui3/base-base/base-base-min.js7
-rw-r--r--js/yui3/base-build/base-build-min.js7
-rw-r--r--js/yui3/base-core/base-core-min.js7
-rw-r--r--js/yui3/base-pluginhost/base-pluginhost-min.js7
-rw-r--r--js/yui3/button-core/button-core-min.js7
-rw-r--r--js/yui3/button-group/button-group-min.js7
-rw-r--r--js/yui3/button-plugin/button-plugin-min.js7
-rw-r--r--js/yui3/button/button-min.js7
-rw-r--r--js/yui3/cache-base/cache-base-min.js7
-rw-r--r--js/yui3/cache-offline/cache-offline-min.js7
-rw-r--r--js/yui3/cache-plugin/cache-plugin-min.js7
-rw-r--r--js/yui3/calendar-base/assets/calendar-base-core.css27
-rw-r--r--js/yui3/calendar-base/assets/skins/night/calendar-base.css7
-rw-r--r--js/yui3/calendar-base/assets/skins/sam/calendar-base.css7
-rw-r--r--js/yui3/calendar-base/calendar-base-min.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_de.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_en.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_fr.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_ja.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_nb-NO.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_pt-BR.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_ru.js7
-rw-r--r--js/yui3/calendar-base/lang/calendar-base_zh-HANT-TW.js7
-rw-r--r--js/yui3/calendar/assets/calendar-core.css37
-rw-r--r--js/yui3/calendar/assets/skins/night/calendar.css7
-rw-r--r--js/yui3/calendar/assets/skins/sam/calendar.css7
-rw-r--r--js/yui3/calendar/calendar-min.js7
-rw-r--r--js/yui3/calendar/lang/calendar.js7
-rw-r--r--js/yui3/calendar/lang/calendar_de.js7
-rw-r--r--js/yui3/calendar/lang/calendar_en.js7
-rw-r--r--js/yui3/calendar/lang/calendar_fr.js7
-rw-r--r--js/yui3/calendar/lang/calendar_ja.js7
-rw-r--r--js/yui3/calendar/lang/calendar_nb-NO.js7
-rw-r--r--js/yui3/calendar/lang/calendar_pt-BR.js7
-rw-r--r--js/yui3/calendar/lang/calendar_ru.js7
-rw-r--r--js/yui3/calendar/lang/calendar_zh-HANT-TW.js7
-rw-r--r--js/yui3/calendarnavigator/assets/calendarnavigator-core.css22
-rw-r--r--js/yui3/calendarnavigator/assets/skins/night/calendarnavigator.css7
-rw-r--r--js/yui3/calendarnavigator/assets/skins/sam/calendarnavigator.css7
-rw-r--r--js/yui3/calendarnavigator/calendarnavigator-min.js7
-rw-r--r--js/yui3/charts-base/charts-base-min.js7
-rw-r--r--js/yui3/charts-legend/charts-legend-min.js7
-rw-r--r--js/yui3/charts/charts-min.js7
-rw-r--r--js/yui3/classnamemanager/classnamemanager-min.js7
-rw-r--r--js/yui3/clickable-rail/assets/slider-base-core.css37
-rw-r--r--js/yui3/clickable-rail/assets/slider-core.css37
-rw-r--r--js/yui3/clickable-rail/assets/thumb-x-oblong-dark.pngbin0 -> 4042 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-x-oblong.pngbin0 -> 961 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-x-oblong2-dark.pngbin0 -> 4045 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-x-oblong2.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-y-oblong-dark.pngbin0 -> 519 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-y-oblong.pngbin0 -> 1023 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-y-oblong2-dark.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/clickable-rail/assets/thumb-y-oblong2.pngbin0 -> 746 bytes
-rw-r--r--js/yui3/clickable-rail/clickable-rail-min.js7
-rw-r--r--js/yui3/console-filters/assets/console-filters-core.css6
-rw-r--r--js/yui3/console-filters/assets/skins/sam/console-filters.css7
-rw-r--r--js/yui3/console-filters/console-filters-min.js7
-rw-r--r--js/yui3/console/assets/console-core.css6
-rw-r--r--js/yui3/console/assets/console-filters-core.css6
-rw-r--r--js/yui3/console/assets/skins/sam/bg.pngbin0 -> 121 bytes
-rw-r--r--js/yui3/console/assets/skins/sam/console-filters.css7
-rw-r--r--js/yui3/console/assets/skins/sam/console.css7
-rw-r--r--js/yui3/console/assets/skins/sam/warn_error.pngbin0 -> 571 bytes
-rw-r--r--js/yui3/console/assets/warn_error.pngbin0 -> 571 bytes
-rw-r--r--js/yui3/console/console-min.js7
-rw-r--r--js/yui3/console/lang/console.js7
-rw-r--r--js/yui3/console/lang/console_en.js7
-rw-r--r--js/yui3/console/lang/console_es.js7
-rw-r--r--js/yui3/console/lang/console_ja.js7
-rw-r--r--js/yui3/cookie/cookie-min.js7
-rw-r--r--js/yui3/createlink-base/createlink-base-min.js7
-rw-r--r--js/yui3/cssbase-context/base-context-min.css7
-rw-r--r--js/yui3/cssbase-context/base-context.css81
-rw-r--r--js/yui3/cssbase-context/cssbase-context-min.css7
-rw-r--r--js/yui3/cssbase-context/cssbase-context.css82
-rw-r--r--js/yui3/cssbase/base-min.css7
-rw-r--r--js/yui3/cssbase/base.css81
-rw-r--r--js/yui3/cssbase/cssbase-min.css7
-rw-r--r--js/yui3/cssbase/cssbase.css82
-rw-r--r--js/yui3/cssbutton/cssbutton-min.css7
-rw-r--r--js/yui3/cssbutton/cssbutton.css149
-rw-r--r--js/yui3/cssfonts-context/cssfonts-context-min.css7
-rw-r--r--js/yui3/cssfonts-context/cssfonts-context.css48
-rw-r--r--js/yui3/cssfonts-context/fonts-context-min.css7
-rw-r--r--js/yui3/cssfonts-context/fonts-context.css48
-rw-r--r--js/yui3/cssfonts/cssfonts-min.css7
-rw-r--r--js/yui3/cssfonts/cssfonts.css48
-rw-r--r--js/yui3/cssfonts/fonts-min.css7
-rw-r--r--js/yui3/cssfonts/fonts.css48
-rw-r--r--js/yui3/cssgrids-base/cssgrids-base-min.css7
-rw-r--r--js/yui3/cssgrids-base/cssgrids-base.css22
-rw-r--r--js/yui3/cssgrids-context-deprecated/grids-context-min.css8
-rw-r--r--js/yui3/cssgrids-context-deprecated/grids-context.css490
-rw-r--r--js/yui3/cssgrids-units/cssgrids-units-min.css7
-rw-r--r--js/yui3/cssgrids-units/cssgrids-units.css155
-rw-r--r--js/yui3/cssgrids/cssgrids-min.css7
-rw-r--r--js/yui3/cssgrids/cssgrids.css168
-rw-r--r--js/yui3/cssgrids/grids-min.css7
-rw-r--r--js/yui3/cssgrids/grids.css167
-rw-r--r--js/yui3/cssreset-context/cssreset-context-min.css7
-rw-r--r--js/yui3/cssreset-context/cssreset-context.css127
-rw-r--r--js/yui3/cssreset-context/reset-context-min.css7
-rw-r--r--js/yui3/cssreset-context/reset-context.css126
-rw-r--r--js/yui3/cssreset/cssreset-min.css7
-rw-r--r--js/yui3/cssreset/cssreset.css127
-rw-r--r--js/yui3/cssreset/reset-min.css7
-rw-r--r--js/yui3/cssreset/reset.css126
-rw-r--r--js/yui3/dataschema-array/dataschema-array-min.js7
-rw-r--r--js/yui3/dataschema-base/dataschema-base-min.js7
-rw-r--r--js/yui3/dataschema-json/dataschema-json-min.js7
-rw-r--r--js/yui3/dataschema-text/dataschema-text-min.js7
-rw-r--r--js/yui3/dataschema-xml/dataschema-xml-min.js7
-rw-r--r--js/yui3/datasource-arrayschema/datasource-arrayschema-min.js7
-rw-r--r--js/yui3/datasource-cache/datasource-cache-min.js7
-rw-r--r--js/yui3/datasource-function/datasource-function-min.js7
-rw-r--r--js/yui3/datasource-get/datasource-get-min.js7
-rw-r--r--js/yui3/datasource-io/datasource-io-min.js7
-rw-r--r--js/yui3/datasource-jsonschema/datasource-jsonschema-min.js7
-rw-r--r--js/yui3/datasource-local/datasource-local-min.js7
-rw-r--r--js/yui3/datasource-polling/datasource-polling-min.js7
-rw-r--r--js/yui3/datasource-textschema/datasource-textschema-min.js7
-rw-r--r--js/yui3/datasource-xmlschema/datasource-xmlschema-min.js7
-rw-r--r--js/yui3/datatable-base-deprecated/assets/datatable-base-deprecated-core.css93
-rw-r--r--js/yui3/datatable-base-deprecated/assets/skins/night/datatable-base-deprecated.css8
-rw-r--r--js/yui3/datatable-base-deprecated/assets/skins/sam/datatable-base-deprecated.css8
-rw-r--r--js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-dn.pngbin0 -> 101 bytes
-rw-r--r--js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-up.pngbin0 -> 99 bytes
-rw-r--r--js/yui3/datatable-base-deprecated/datatable-base-deprecated-min.js8
-rw-r--r--js/yui3/datatable-base/assets/datatable-base-core.css10
-rw-r--r--js/yui3/datatable-base/assets/skins/night/datatable-base.css7
-rw-r--r--js/yui3/datatable-base/assets/skins/sam/datatable-base.css7
-rw-r--r--js/yui3/datatable-base/datatable-base-min.js7
-rw-r--r--js/yui3/datatable-body/datatable-body-min.js7
-rw-r--r--js/yui3/datatable-column-widths/datatable-column-widths-min.js7
-rw-r--r--js/yui3/datatable-core/datatable-core-min.js7
-rw-r--r--js/yui3/datatable-datasource-deprecated/datatable-datasource-deprecated-min.js7
-rw-r--r--js/yui3/datatable-datasource/datatable-datasource-min.js7
-rw-r--r--js/yui3/datatable-head/datatable-head-min.js7
-rw-r--r--js/yui3/datatable-message/assets/datatable-message-core.css14
-rw-r--r--js/yui3/datatable-message/assets/skins/night/datatable-message.css7
-rw-r--r--js/yui3/datatable-message/assets/skins/sam/datatable-message.css7
-rw-r--r--js/yui3/datatable-message/datatable-message-min.js7
-rw-r--r--js/yui3/datatable-message/lang/datatable-message.js7
-rw-r--r--js/yui3/datatable-message/lang/datatable-message_en.js7
-rw-r--r--js/yui3/datatable-mutable/datatable-mutable-min.js7
-rw-r--r--js/yui3/datatable-scroll-deprecated/datatable-scroll-deprecated-min.js8
-rw-r--r--js/yui3/datatable-scroll/assets/datatable-scroll-core.css77
-rw-r--r--js/yui3/datatable-scroll/assets/skins/night/datatable-scroll.css7
-rw-r--r--js/yui3/datatable-scroll/assets/skins/sam/datatable-scroll.css7
-rw-r--r--js/yui3/datatable-scroll/datatable-scroll-min.js7
-rw-r--r--js/yui3/datatable-sort-deprecated/datatable-sort-deprecated-min.js7
-rw-r--r--js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated.js7
-rw-r--r--js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated_en.js7
-rw-r--r--js/yui3/datatable-sort/assets/datatable-sort-core.css15
-rw-r--r--js/yui3/datatable-sort/assets/skins/night/datatable-sort.css7
-rw-r--r--js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite-ie.pngbin0 -> 3629 bytes
-rw-r--r--js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite.pngbin0 -> 2885 bytes
-rw-r--r--js/yui3/datatable-sort/assets/skins/sam/datatable-sort.css7
-rw-r--r--js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite-ie.pngbin0 -> 3628 bytes
-rw-r--r--js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite.pngbin0 -> 2884 bytes
-rw-r--r--js/yui3/datatable-sort/datatable-sort-min.js7
-rw-r--r--js/yui3/datatable-sort/lang/datatable-sort.js7
-rw-r--r--js/yui3/datatable-sort/lang/datatable-sort_en.js7
-rw-r--r--js/yui3/datatable-table/datatable-table-min.js7
-rw-r--r--js/yui3/datatype-date-format/datatype-date-format-min.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ar-JO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ar.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ca-ES.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ca.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_da-DK.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_da.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_de-AT.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_de-DE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_de.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_el-GR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_el.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-AU.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-CA.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-GB.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-IE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-IN.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-JO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-MY.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-NZ.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-PH.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-SG.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en-US.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_en.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-AR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-BO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-CL.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-CO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-EC.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-ES.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-MX.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-PE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-PY.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-US.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-UY.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es-VE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_es.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fi-FI.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fi.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fr-BE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fr-CA.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fr-FR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_fr.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_hi-IN.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_hi.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_id-ID.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_id.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_it-IT.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_it.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ja-JP.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ja.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ko-KR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ko.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ms-MY.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ms.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_nb-NO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_nb.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_nl-BE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_nl-NL.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_nl.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_pl-PL.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_pl.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_pt-BR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_pt.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ro-RO.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ro.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ru-RU.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_ru.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_sv-SE.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_sv.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_th-TH.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_th.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_tr-TR.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_tr.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_vi-VN.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_vi.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans-CN.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-HK.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-TW.js7
-rw-r--r--js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant.js7
-rw-r--r--js/yui3/datatype-date-math/datatype-date-math-min.js7
-rw-r--r--js/yui3/datatype-date-parse/datatype-date-parse-min.js7
-rw-r--r--js/yui3/datatype-number-format/datatype-number-format-min.js7
-rw-r--r--js/yui3/datatype-number-parse/datatype-number-parse-min.js7
-rw-r--r--js/yui3/datatype-xml-format/datatype-xml-format-min.js7
-rw-r--r--js/yui3/datatype-xml-parse/datatype-xml-parse-min.js7
-rw-r--r--js/yui3/dd-constrain/dd-constrain-min.js7
-rw-r--r--js/yui3/dd-ddm-base/dd-ddm-base-min.js7
-rw-r--r--js/yui3/dd-ddm-drop/dd-ddm-drop-min.js7
-rw-r--r--js/yui3/dd-ddm/dd-ddm-min.js7
-rw-r--r--js/yui3/dd-delegate/dd-delegate-min.js7
-rw-r--r--js/yui3/dd-drag/dd-drag-min.js7
-rw-r--r--js/yui3/dd-drop-plugin/dd-drop-plugin-min.js7
-rw-r--r--js/yui3/dd-drop/dd-drop-min.js7
-rw-r--r--js/yui3/dd-gestures/dd-gestures-min.js7
-rw-r--r--js/yui3/dd-plugin/dd-plugin-min.js7
-rw-r--r--js/yui3/dd-proxy/dd-proxy-min.js7
-rw-r--r--js/yui3/dd-scroll/dd-scroll-min.js7
-rw-r--r--js/yui3/dial/assets/dial-core.css48
-rw-r--r--js/yui3/dial/assets/skins/night/dial.css7
-rw-r--r--js/yui3/dial/assets/skins/sam/dial.css7
-rw-r--r--js/yui3/dial/dial-min.js7
-rw-r--r--js/yui3/dial/lang/dial.js7
-rw-r--r--js/yui3/dial/lang/dial_en.js7
-rw-r--r--js/yui3/dial/lang/dial_es.js7
-rw-r--r--js/yui3/dom-attrs/dom-attrs-min.js7
-rw-r--r--js/yui3/dom-base/dom-base-min.js7
-rw-r--r--js/yui3/dom-class/dom-class-min.js7
-rw-r--r--js/yui3/dom-core/dom-core-min.js7
-rw-r--r--js/yui3/dom-create/dom-create-min.js7
-rw-r--r--js/yui3/dom-deprecated/dom-deprecated-min.js7
-rw-r--r--js/yui3/dom-screen/dom-screen-min.js7
-rw-r--r--js/yui3/dom-size/dom-size-min.js7
-rw-r--r--js/yui3/dom-style-ie/dom-style-ie-min.js7
-rw-r--r--js/yui3/dom-style/dom-style-min.js7
-rw-r--r--js/yui3/dump/dump-min.js7
-rw-r--r--js/yui3/editor-base/editor-base-min.js7
-rw-r--r--js/yui3/editor-bidi/editor-bidi-min.js7
-rw-r--r--js/yui3/editor-br/editor-br-min.js7
-rw-r--r--js/yui3/editor-lists/editor-lists-min.js7
-rw-r--r--js/yui3/editor-para-base/editor-para-base-min.js7
-rw-r--r--js/yui3/editor-para-ie/editor-para-ie-min.js7
-rw-r--r--js/yui3/editor-para/editor-para-min.js7
-rw-r--r--js/yui3/editor-selection/editor-selection-min.js7
-rw-r--r--js/yui3/editor-tab/editor-tab-min.js7
-rw-r--r--js/yui3/escape/escape-min.js7
-rw-r--r--js/yui3/event-base-ie/event-base-ie-min.js9
-rw-r--r--js/yui3/event-base/event-base-min.js7
-rw-r--r--js/yui3/event-contextmenu/event-contextmenu-min.js7
-rw-r--r--js/yui3/event-custom-base/event-custom-base-min.js7
-rw-r--r--js/yui3/event-custom-complex/event-custom-complex-min.js7
-rw-r--r--js/yui3/event-delegate/event-delegate-min.js7
-rw-r--r--js/yui3/event-flick/event-flick-min.js7
-rw-r--r--js/yui3/event-focus/event-focus-min.js7
-rw-r--r--js/yui3/event-hover/event-hover-min.js7
-rw-r--r--js/yui3/event-key/event-key-min.js7
-rw-r--r--js/yui3/event-mouseenter/event-mouseenter-min.js7
-rw-r--r--js/yui3/event-mousewheel/event-mousewheel-min.js7
-rw-r--r--js/yui3/event-move/event-move-min.js7
-rw-r--r--js/yui3/event-outside/event-outside-min.js7
-rw-r--r--js/yui3/event-resize/event-resize-min.js7
-rw-r--r--js/yui3/event-simulate/event-simulate-min.js7
-rw-r--r--js/yui3/event-synthetic/event-synthetic-min.js7
-rw-r--r--js/yui3/event-tap/event-tap-min.js7
-rw-r--r--js/yui3/event-touch/event-touch-min.js7
-rw-r--r--js/yui3/event-valuechange/event-valuechange-min.js7
-rw-r--r--js/yui3/exec-command/exec-command-min.js7
-rw-r--r--js/yui3/features/features-min.js7
-rw-r--r--js/yui3/file-flash/file-flash-min.js7
-rw-r--r--js/yui3/file-html5/file-html5-min.js7
-rw-r--r--js/yui3/file/file-min.js7
-rw-r--r--js/yui3/frame/frame-min.js7
-rw-r--r--js/yui3/gallery-datatable-paginator/gallery-datatable-paginator-min.js2
-rw-r--r--js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.pngbin0 -> 218 bytes
-rw-r--r--js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css1
-rw-r--r--js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.pngbin0 -> 203 bytes
-rw-r--r--js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js383
-rw-r--r--js/yui3/gallery-funcprog/gallery-funcprog-min.js1
-rw-r--r--js/yui3/gallery-math/gallery-math-min.js1
-rw-r--r--js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js1
-rw-r--r--js/yui3/gallery-object-extras/gallery-object-extras-min.js1
-rw-r--r--js/yui3/gallery-paginator-view/assets/skins/sam/gallery-paginator-view.css1
-rw-r--r--js/yui3/gesture-simulate/gesture-simulate-min.js7
-rw-r--r--js/yui3/get-nodejs/get-min.js7
-rw-r--r--js/yui3/get-nodejs/get-nodejs-min.js7
-rw-r--r--js/yui3/get/get-min.js7
-rw-r--r--js/yui3/graphics-canvas-default/graphics-canvas-default-min.js7
-rw-r--r--js/yui3/graphics-canvas/graphics-canvas-min.js7
-rw-r--r--js/yui3/graphics-svg-default/graphics-svg-default-min.js7
-rw-r--r--js/yui3/graphics-svg/graphics-svg-min.js7
-rw-r--r--js/yui3/graphics-vml-default/graphics-vml-default-min.js7
-rw-r--r--js/yui3/graphics-vml/graphics-vml-min.js7
-rw-r--r--js/yui3/graphics/graphics-min.js7
-rw-r--r--js/yui3/handlebars-base/handlebars-base-min.js12
-rw-r--r--js/yui3/handlebars-compiler/handlebars-compiler-min.js12
-rw-r--r--js/yui3/highlight-accentfold/highlight-accentfold-min.js7
-rw-r--r--js/yui3/highlight-base/highlight-base-min.js7
-rw-r--r--js/yui3/history-base/history-base-min.js7
-rw-r--r--js/yui3/history-hash-ie/history-hash-ie-min.js7
-rw-r--r--js/yui3/history-hash/history-hash-min.js7
-rw-r--r--js/yui3/history-html5/history-html5-min.js7
-rw-r--r--js/yui3/imageloader/imageloader-min.js7
-rw-r--r--js/yui3/intl-base/intl-base-min.js7
-rw-r--r--js/yui3/intl/intl-min.js7
-rw-r--r--js/yui3/io-base/io-base-min.js7
-rw-r--r--js/yui3/io-form/io-form-min.js7
-rw-r--r--js/yui3/io-nodejs/io-nodejs-min.js7
-rw-r--r--js/yui3/io-queue/io-queue-min.js7
-rw-r--r--js/yui3/io-upload-iframe/io-upload-iframe-min.js7
-rw-r--r--js/yui3/io-xdr/io-xdr-min.js7
-rw-r--r--js/yui3/io-xdr/io.swfbin0 -> 2247 bytes
-rw-r--r--js/yui3/json-parse/json-parse-min.js7
-rw-r--r--js/yui3/json-stringify/json-stringify-min.js7
-rw-r--r--js/yui3/jsonp-url/jsonp-url-min.js7
-rw-r--r--js/yui3/jsonp/jsonp-min.js7
-rw-r--r--js/yui3/lazy-model-list/lazy-model-list-min.js7
-rw-r--r--js/yui3/loader-base/loader-base-min.js7
-rw-r--r--js/yui3/loader-rollup/loader-rollup-min.js7
-rw-r--r--js/yui3/loader-yui3/loader-yui3-min.js7
-rw-r--r--js/yui3/loader/loader-min.js7
-rw-r--r--js/yui3/matrix/matrix-min.js7
-rw-r--r--js/yui3/model-list/model-list-min.js7
-rw-r--r--js/yui3/model-sync-rest/model-sync-rest-min.js7
-rw-r--r--js/yui3/model/model-min.js7
-rw-r--r--js/yui3/node-base/node-base-min.js7
-rw-r--r--js/yui3/node-core/node-core-min.js7
-rw-r--r--js/yui3/node-deprecated/node-deprecated-min.js7
-rw-r--r--js/yui3/node-event-delegate/node-event-delegate-min.js7
-rw-r--r--js/yui3/node-event-html5/node-event-html5-min.js7
-rw-r--r--js/yui3/node-event-simulate/node-event-simulate-min.js7
-rw-r--r--js/yui3/node-flick/assets/node-flick-core.css14
-rw-r--r--js/yui3/node-flick/assets/skins/sam/node-flick.css7
-rw-r--r--js/yui3/node-flick/node-flick-min.js7
-rw-r--r--js/yui3/node-focusmanager/node-focusmanager-min.js7
-rw-r--r--js/yui3/node-load/node-load-min.js7
-rw-r--r--js/yui3/node-menunav/assets/node-menunav-core.css175
-rw-r--r--js/yui3/node-menunav/assets/skins/night/horizontal-menu-submenu-indicator.pngbin0 -> 157 bytes
-rw-r--r--js/yui3/node-menunav/assets/skins/night/node-menunav.css7
-rw-r--r--js/yui3/node-menunav/assets/skins/night/vertical-menu-submenu-indicator.pngbin0 -> 156 bytes
-rw-r--r--js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-indicator.pngbin0 -> 157 bytes
-rw-r--r--js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-toggle.pngbin0 -> 183 bytes
-rw-r--r--js/yui3/node-menunav/assets/skins/sam/node-menunav.css7
-rw-r--r--js/yui3/node-menunav/assets/skins/sam/vertical-menu-submenu-indicator.pngbin0 -> 156 bytes
-rw-r--r--js/yui3/node-menunav/node-menunav-min.js7
-rw-r--r--js/yui3/node-pluginhost/node-pluginhost-min.js7
-rw-r--r--js/yui3/node-screen/node-screen-min.js7
-rw-r--r--js/yui3/node-scroll-info/node-scroll-info-min.js7
-rw-r--r--js/yui3/node-style/node-style-min.js7
-rw-r--r--js/yui3/oop/oop-min.js7
-rw-r--r--js/yui3/overlay/assets/overlay-core.css17
-rw-r--r--js/yui3/overlay/assets/skins/night/overlay.css7
-rw-r--r--js/yui3/overlay/assets/skins/sam/overlay.css7
-rw-r--r--js/yui3/overlay/overlay-min.js7
-rw-r--r--js/yui3/panel/assets/panel-core.css28
-rw-r--r--js/yui3/panel/assets/skins/night/panel.css7
-rw-r--r--js/yui3/panel/assets/skins/night/sprite_icons.pngbin0 -> 176 bytes
-rw-r--r--js/yui3/panel/assets/skins/sam/panel.css7
-rw-r--r--js/yui3/panel/assets/skins/sam/sprite_icons.pngbin0 -> 176 bytes
-rw-r--r--js/yui3/panel/panel-min.js7
-rw-r--r--js/yui3/parallel/parallel-min.js7
-rw-r--r--js/yui3/pjax-base/pjax-base-min.js7
-rw-r--r--js/yui3/pjax-content/pjax-content-min.js7
-rw-r--r--js/yui3/pjax-plugin/pjax-plugin-min.js7
-rw-r--r--js/yui3/pjax/pjax-min.js7
-rw-r--r--js/yui3/plugin/plugin-min.js7
-rw-r--r--js/yui3/pluginhost-base/pluginhost-base-min.js7
-rw-r--r--js/yui3/pluginhost-config/pluginhost-config-min.js7
-rw-r--r--js/yui3/profiler/profiler-min.js7
-rw-r--r--js/yui3/querystring-parse-simple/querystring-parse-simple-min.js7
-rw-r--r--js/yui3/querystring-parse/querystring-parse-min.js7
-rw-r--r--js/yui3/querystring-stringify-simple/querystring-stringify-simple-min.js7
-rw-r--r--js/yui3/querystring-stringify/querystring-stringify-min.js7
-rw-r--r--js/yui3/queue-promote/queue-promote-min.js7
-rw-r--r--js/yui3/range-slider/assets/slider-base-core.css37
-rw-r--r--js/yui3/range-slider/assets/slider-core.css37
-rw-r--r--js/yui3/range-slider/assets/thumb-x-oblong-dark.pngbin0 -> 4042 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-x-oblong.pngbin0 -> 961 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-x-oblong2-dark.pngbin0 -> 4045 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-x-oblong2.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-y-oblong-dark.pngbin0 -> 519 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-y-oblong.pngbin0 -> 1023 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-y-oblong2-dark.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/range-slider/assets/thumb-y-oblong2.pngbin0 -> 746 bytes
-rw-r--r--js/yui3/range-slider/range-slider-min.js7
-rw-r--r--js/yui3/recordset-base/recordset-base-min.js7
-rw-r--r--js/yui3/recordset-filter/recordset-filter-min.js7
-rw-r--r--js/yui3/recordset-indexer/recordset-indexer-min.js7
-rw-r--r--js/yui3/recordset-sort/recordset-sort-min.js7
-rw-r--r--js/yui3/resize-base/assets/resize-base-core.css247
-rw-r--r--js/yui3/resize-base/assets/skins/night/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-base/assets/skins/night/resize-base.css7
-rw-r--r--js/yui3/resize-base/assets/skins/sam/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-base/assets/skins/sam/resize-base.css7
-rw-r--r--js/yui3/resize-base/resize-base-min.js7
-rw-r--r--js/yui3/resize-constrain/assets/resize-base-core.css247
-rw-r--r--js/yui3/resize-constrain/assets/skins/night/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-constrain/assets/skins/night/resize-base-skin.css52
-rw-r--r--js/yui3/resize-constrain/assets/skins/sam/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-constrain/assets/skins/sam/resize-base-skin.css52
-rw-r--r--js/yui3/resize-constrain/resize-constrain-min.js7
-rw-r--r--js/yui3/resize-plugin/assets/resize-base-core.css247
-rw-r--r--js/yui3/resize-plugin/assets/skins/night/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-plugin/assets/skins/night/resize-base-skin.css52
-rw-r--r--js/yui3/resize-plugin/assets/skins/sam/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-plugin/assets/skins/sam/resize-base-skin.css52
-rw-r--r--js/yui3/resize-plugin/resize-plugin-min.js7
-rw-r--r--js/yui3/resize-proxy/assets/resize-base-core.css247
-rw-r--r--js/yui3/resize-proxy/assets/skins/night/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-proxy/assets/skins/night/resize-base-skin.css52
-rw-r--r--js/yui3/resize-proxy/assets/skins/sam/arrows.pngbin0 -> 258 bytes
-rw-r--r--js/yui3/resize-proxy/assets/skins/sam/resize-base-skin.css52
-rw-r--r--js/yui3/resize-proxy/resize-proxy-min.js7
-rw-r--r--js/yui3/router/router-min.js7
-rw-r--r--js/yui3/scrollview-base-ie/scrollview-base-ie-min.js7
-rw-r--r--js/yui3/scrollview-base/assets/scrollview-base-core.css20
-rw-r--r--js/yui3/scrollview-base/assets/skins/night/scrollview-base.css7
-rw-r--r--js/yui3/scrollview-base/assets/skins/sam/scrollview-base.css7
-rw-r--r--js/yui3/scrollview-base/scrollview-base-min.js7
-rw-r--r--js/yui3/scrollview-list/assets/scrollview-list-core.css6
-rw-r--r--js/yui3/scrollview-list/assets/skins/night/scrollview-list.css7
-rw-r--r--js/yui3/scrollview-list/assets/skins/sam/scrollview-list.css7
-rw-r--r--js/yui3/scrollview-list/scrollview-list-min.js7
-rw-r--r--js/yui3/scrollview-paginator/scrollview-paginator-min.js7
-rw-r--r--js/yui3/scrollview-scrollbars/assets/scrollview-scrollbars-core.css101
-rw-r--r--js/yui3/scrollview-scrollbars/assets/skins/night/scrollview-scrollbars.css7
-rw-r--r--js/yui3/scrollview-scrollbars/assets/skins/sam/scrollview-scrollbars.css7
-rw-r--r--js/yui3/scrollview-scrollbars/scrollview-scrollbars-min.js7
-rw-r--r--js/yui3/scrollview/scrollview-min.js7
-rw-r--r--js/yui3/selector-css2/selector-css2-min.js7
-rw-r--r--js/yui3/selector-css3/selector-css3-min.js7
-rw-r--r--js/yui3/selector-native/selector-native-min.js7
-rw-r--r--js/yui3/selector/selector-min.js7
-rw-r--r--js/yui3/shim-plugin/shim-plugin-min.js7
-rw-r--r--js/yui3/simpleyui/simpleyui-min.js7
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/rail-x.pngbin0 -> 3668 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/rail-y.pngbin0 -> 3664 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/slider-skin.css97
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/thumb-x.pngbin0 -> 400 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio-light/thumb-y.pngbin0 -> 503 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio/rail-x.pngbin0 -> 3662 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio/rail-y.pngbin0 -> 3660 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/audio/slider-skin.css97
-rw-r--r--js/yui3/slider-base/assets/skins/audio/thumb-x.pngbin0 -> 3742 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/audio/thumb-y.pngbin0 -> 414 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-x-dots.pngbin0 -> 3651 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-x-lines.pngbin0 -> 3673 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-x.pngbin0 -> 3710 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-y-dots.pngbin0 -> 3642 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-y-lines.pngbin0 -> 3667 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/rail-y.pngbin0 -> 3673 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/slider-skin.css97
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/thumb-x-line.pngbin0 -> 3845 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/thumb-x.pngbin0 -> 4166 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/thumb-y-line.pngbin0 -> 518 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule-dark/thumb-y.pngbin0 -> 685 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-x-dots.pngbin0 -> 3655 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-x-lines.pngbin0 -> 3669 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-x.pngbin0 -> 3701 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-y-dots.pngbin0 -> 3643 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-y-lines.pngbin0 -> 3643 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/rail-y.pngbin0 -> 3689 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/slider-skin.css99
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/thumb-x-line.pngbin0 -> 828 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/thumb-x.pngbin0 -> 768 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/thumb-y-line.pngbin0 -> 669 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/thumb-y-lines.pngbin0 -> 3665 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/capsule/thumb-y.pngbin0 -> 541 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/rail-x-lines.pngbin0 -> 301 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/rail-x.pngbin0 -> 273 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/rail-y-lines.pngbin0 -> 262 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/rail-y.pngbin0 -> 321 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/night/slider-skin.css93
-rw-r--r--js/yui3/slider-base/assets/skins/night/thumb-x.pngbin0 -> 467 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/night/thumb-y.pngbin0 -> 566 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/rail-x.pngbin0 -> 3637 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/rail-y.pngbin0 -> 3635 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/slider-skin.css95
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/thumb-x-grip.pngbin0 -> 4365 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/thumb-x.pngbin0 -> 4333 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/thumb-y-grip.pngbin0 -> 648 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round-dark/thumb-y.pngbin0 -> 835 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/rail-x.pngbin0 -> 3642 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/rail-y.pngbin0 -> 3637 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/round/slider-skin.css95
-rw-r--r--js/yui3/slider-base/assets/skins/round/thumb-x-grip.pngbin0 -> 692 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/thumb-x.pngbin0 -> 4143 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/thumb-y-grip.pngbin0 -> 731 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/round/thumb-y.pngbin0 -> 890 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/rail-x-lines.pngbin0 -> 3647 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/rail-x.pngbin0 -> 3635 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/rail-y-lines.pngbin0 -> 3640 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/rail-y.pngbin0 -> 3628 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/slider-skin.css93
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/thumb-x.pngbin0 -> 3853 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam-dark/thumb-y.pngbin0 -> 602 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/rail-x-lines.pngbin0 -> 3656 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/rail-x.pngbin0 -> 3639 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/rail-y-lines.pngbin0 -> 3642 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/rail-y.pngbin0 -> 3629 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/slider-base.css7
-rw-r--r--js/yui3/slider-base/assets/skins/sam/slider-skin.css93
-rw-r--r--js/yui3/slider-base/assets/skins/sam/thumb-x.pngbin0 -> 3873 bytes
-rw-r--r--js/yui3/slider-base/assets/skins/sam/thumb-y.pngbin0 -> 3860 bytes
-rw-r--r--js/yui3/slider-base/assets/slider-base-core.css37
-rw-r--r--js/yui3/slider-base/assets/slider-core.css37
-rw-r--r--js/yui3/slider-base/assets/thumb-x-oblong-dark.pngbin0 -> 4042 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-x-oblong.pngbin0 -> 961 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-x-oblong2-dark.pngbin0 -> 4045 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-x-oblong2.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-y-oblong-dark.pngbin0 -> 519 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-y-oblong.pngbin0 -> 1023 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-y-oblong2-dark.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/slider-base/assets/thumb-y-oblong2.pngbin0 -> 746 bytes
-rw-r--r--js/yui3/slider-base/slider-base-min.js7
-rw-r--r--js/yui3/slider-value-range/assets/slider-base-core.css37
-rw-r--r--js/yui3/slider-value-range/assets/slider-core.css37
-rw-r--r--js/yui3/slider-value-range/assets/thumb-x-oblong-dark.pngbin0 -> 4042 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-x-oblong.pngbin0 -> 961 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-x-oblong2-dark.pngbin0 -> 4045 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-x-oblong2.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-y-oblong-dark.pngbin0 -> 519 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-y-oblong.pngbin0 -> 1023 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-y-oblong2-dark.pngbin0 -> 706 bytes
-rw-r--r--js/yui3/slider-value-range/assets/thumb-y-oblong2.pngbin0 -> 746 bytes
-rw-r--r--js/yui3/slider-value-range/slider-value-range-min.js7
-rw-r--r--js/yui3/sortable-scroll/sortable-scroll-min.js7
-rw-r--r--js/yui3/sortable/sortable-min.js7
-rw-r--r--js/yui3/stylesheet/stylesheet-min.js7
-rw-r--r--js/yui3/substitute/substitute-min.js7
-rw-r--r--js/yui3/swf/swf-min.js7
-rw-r--r--js/yui3/swfdetect/swfdetect-min.js7
-rw-r--r--js/yui3/tabview-base/assets/tabview-core.css48
-rw-r--r--js/yui3/tabview-base/assets/tabview.css28
-rw-r--r--js/yui3/tabview-base/tabview-base-min.js7
-rw-r--r--js/yui3/tabview-plugin/assets/tabview-core.css48
-rw-r--r--js/yui3/tabview-plugin/assets/tabview.css28
-rw-r--r--js/yui3/tabview-plugin/tabview-plugin-min.js7
-rw-r--r--js/yui3/tabview/assets/skins/night/tabview.css7
-rw-r--r--js/yui3/tabview/assets/skins/sam/tabview.css7
-rw-r--r--js/yui3/tabview/assets/tabview-core.css48
-rw-r--r--js/yui3/tabview/assets/tabview.css28
-rw-r--r--js/yui3/tabview/tabview-min.js7
-rw-r--r--js/yui3/test-console/assets/skins/sam/test-console.css7
-rw-r--r--js/yui3/test-console/assets/test-console-core.css14
-rw-r--r--js/yui3/test-console/test-console-min.js7
-rw-r--r--js/yui3/test/test-min.js7
-rw-r--r--js/yui3/text-accentfold/text-accentfold-min.js7
-rw-r--r--js/yui3/text-data-accentfold/text-data-accentfold-min.js7
-rw-r--r--js/yui3/text-data-wordbreak/text-data-wordbreak-min.js7
-rw-r--r--js/yui3/text-wordbreak/text-wordbreak-min.js7
-rw-r--r--js/yui3/transition-timer/transition-timer-min.js7
-rw-r--r--js/yui3/transition/transition-min.js7
-rw-r--r--js/yui3/uploader-deprecated/assets/uploader.swfbin0 -> 6611 bytes
-rw-r--r--js/yui3/uploader-deprecated/uploader-deprecated-min.js7
-rw-r--r--js/yui3/uploader-flash/assets/uploader-flash-core.css10
-rw-r--r--js/yui3/uploader-flash/uploader-flash-min.js7
-rw-r--r--js/yui3/uploader-html5/assets/uploader-flash-core.css10
-rw-r--r--js/yui3/uploader-html5/uploader-html5-min.js7
-rw-r--r--js/yui3/uploader-queue/assets/uploader-flash-core.css10
-rw-r--r--js/yui3/uploader-queue/uploader-queue-min.js7
-rw-r--r--js/yui3/uploader/assets/flashuploader.swfbin0 -> 5080 bytes
-rw-r--r--js/yui3/uploader/assets/uploader-flash-core.css10
-rw-r--r--js/yui3/uploader/uploader-min.js7
-rw-r--r--js/yui3/view-node-map/view-node-map-min.js7
-rw-r--r--js/yui3/view/view-min.js7
-rw-r--r--js/yui3/widget-anim/widget-anim-min.js7
-rw-r--r--js/yui3/widget-autohide/widget-autohide-min.js7
-rw-r--r--js/yui3/widget-base-ie/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-base-ie/widget-base-ie-min.js7
-rw-r--r--js/yui3/widget-base/assets/skins/night/widget-base.css7
-rw-r--r--js/yui3/widget-base/assets/skins/sam/widget-base.css7
-rw-r--r--js/yui3/widget-base/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-base/widget-base-min.js7
-rw-r--r--js/yui3/widget-buttons/assets/skins/night/sprite_icons.gifbin0 -> 142 bytes
-rw-r--r--js/yui3/widget-buttons/assets/skins/night/widget-buttons.css7
-rw-r--r--js/yui3/widget-buttons/assets/skins/sam/sprite_icons.gifbin0 -> 142 bytes
-rw-r--r--js/yui3/widget-buttons/assets/skins/sam/widget-buttons.css7
-rw-r--r--js/yui3/widget-buttons/assets/widget-buttons-core.css21
-rw-r--r--js/yui3/widget-buttons/widget-buttons-min.js7
-rw-r--r--js/yui3/widget-child/widget-child-min.js7
-rw-r--r--js/yui3/widget-htmlparser/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-htmlparser/widget-htmlparser-min.js7
-rw-r--r--js/yui3/widget-locale/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-locale/widget-locale-min.js7
-rw-r--r--js/yui3/widget-modality/assets/skins/night/widget-modality.css7
-rw-r--r--js/yui3/widget-modality/assets/skins/sam/widget-modality.css7
-rw-r--r--js/yui3/widget-modality/assets/widget-modality-core.css7
-rw-r--r--js/yui3/widget-modality/widget-modality-min.js9
-rw-r--r--js/yui3/widget-parent/widget-parent-min.js7
-rw-r--r--js/yui3/widget-position-align/widget-position-align-min.js7
-rw-r--r--js/yui3/widget-position-constrain/widget-position-constrain-min.js7
-rw-r--r--js/yui3/widget-position/widget-position-min.js7
-rw-r--r--js/yui3/widget-skin/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-skin/widget-skin-min.js7
-rw-r--r--js/yui3/widget-stack/assets/skins/night/widget-stack.css7
-rw-r--r--js/yui3/widget-stack/assets/skins/sam/widget-stack.css7
-rw-r--r--js/yui3/widget-stack/assets/widget-stack-core.css25
-rw-r--r--js/yui3/widget-stack/widget-stack-min.js7
-rw-r--r--js/yui3/widget-stdmod/widget-stdmod-min.js7
-rw-r--r--js/yui3/widget-uievents/assets/widget-base-core.css26
-rw-r--r--js/yui3/widget-uievents/widget-uievents-min.js7
-rw-r--r--js/yui3/yql-nodejs/yql-nodejs-min.js7
-rw-r--r--js/yui3/yql-winjs/yql-winjs-min.js7
-rw-r--r--js/yui3/yql/yql-min.js7
-rw-r--r--js/yui3/yui-base/yui-base-min.js7
-rw-r--r--js/yui3/yui-core/yui-core-min.js7
-rw-r--r--js/yui3/yui-later/yui-later-min.js7
-rw-r--r--js/yui3/yui-log-nodejs/yui-log-nodejs-min.js7
-rw-r--r--js/yui3/yui-log/yui-log-min.js7
-rw-r--r--js/yui3/yui-nodejs/yui-nodejs-min.js7
-rw-r--r--js/yui3/yui-throttle/yui-throttle-min.js9
-rw-r--r--js/yui3/yui/yui-min.js7
-rwxr-xr-xlong_list.cgi36
-rw-r--r--mod_perl.pl10
-rwxr-xr-xpost_bug.cgi6
-rwxr-xr-xprocess_bug.cgi48
-rwxr-xr-xquips.cgi1
-rwxr-xr-xreport.cgi8
-rwxr-xr-xrequest.cgi41
-rw-r--r--robots.txt15
-rwxr-xr-xsanitycheck.cgi2
-rwxr-xr-xsearch_plugin.cgi8
-rwxr-xr-xshow_bug.cgi6
-rwxr-xr-xshowattachment.cgi40
-rwxr-xr-xshowdependencygraph.cgi16
-rw-r--r--skins/contrib/Dusk-Helvetica/buglist.css24
-rw-r--r--skins/contrib/Dusk-Helvetica/global.css263
-rw-r--r--skins/contrib/Dusk-Helvetica/index.css9
-rw-r--r--skins/contrib/Dusk-Segoe/buglist.css24
-rw-r--r--skins/contrib/Dusk-Segoe/global.css263
-rw-r--r--skins/contrib/Dusk-Segoe/index.css9
-rw-r--r--skins/contrib/Dusk-Segoe/show_bug.css3
-rw-r--r--skins/contrib/Dusk/global.css6
-rw-r--r--skins/contrib/Mozilla/bugzilla-magnifier.pngbin0 -> 7491 bytes
-rw-r--r--skins/contrib/Mozilla/bugzilla-papericon.pngbin0 -> 3800 bytes
-rw-r--r--skins/contrib/Mozilla/bugzilla-person-alternate.pngbin0 -> 8359 bytes
-rw-r--r--skins/contrib/Mozilla/bugzilla-person.pngbin0 -> 6648 bytes
-rw-r--r--skins/contrib/Mozilla/bugzilla-questionmark2.pngbin0 -> 11552 bytes
-rw-r--r--skins/contrib/Mozilla/dropdown.pngbin0 -> 130 bytes
-rw-r--r--skins/contrib/Mozilla/footer-mozilla.pngbin0 -> 528 bytes
-rw-r--r--skins/contrib/Mozilla/global.css666
-rw-r--r--skins/contrib/Mozilla/grain.pngbin0 -> 47497 bytes
-rw-r--r--skins/contrib/Mozilla/index.css20
-rw-r--r--skins/contrib/Mozilla/noise.pngbin0 -> 3077 bytes
-rw-r--r--skins/contrib/Mozilla/search.pngbin0 -> 199 bytes
-rw-r--r--skins/custom/IE-fixes.css4
-rw-r--r--skins/custom/bug_groups.css29
-rw-r--r--skins/custom/buglist.css41
-rw-r--r--skins/custom/create_bug.css34
-rw-r--r--skins/custom/global.css67
-rw-r--r--skins/custom/index.css31
-rw-r--r--skins/custom/search_form.css6
-rw-r--r--skins/custom/show_bug.css86
-rw-r--r--skins/standard/buglist.css16
-rw-r--r--skins/standard/enter_bug.css2
-rw-r--r--skins/standard/global.css10
-rw-r--r--skins/standard/guided.css4
-rw-r--r--skins/standard/reports.css5
-rw-r--r--t/001compile.t5
-rw-r--r--t/004template.t13
-rw-r--r--t/008filter.t5
-rw-r--r--t/012throwables.t4
-rw-r--r--t/Support/Files.pm13
-rw-r--r--template/en/default/account/auth/login-small.html.tmpl8
-rw-r--r--template/en/default/account/auth/login.html.tmpl8
-rw-r--r--template/en/default/account/create.html.tmpl2
-rw-r--r--template/en/default/account/prefs/email.html.tmpl47
-rw-r--r--template/en/default/account/prefs/permissions.html.tmpl4
-rw-r--r--template/en/default/account/prefs/saved-searches.html.tmpl2
-rw-r--r--template/en/default/account/profile-activity.html.tmpl2
-rw-r--r--template/en/default/admin/flag-type/edit.html.tmpl2
-rw-r--r--template/en/default/admin/params/advanced.html.tmpl8
-rw-r--r--template/en/default/admin/params/auth.html.tmpl6
-rw-r--r--template/en/default/admin/users/edit.html.tmpl12
-rw-r--r--template/en/default/admin/users/list.html.tmpl11
-rw-r--r--template/en/default/attachment/createformcontents.html.tmpl2
-rw-r--r--template/en/default/attachment/delete_reason.txt.tmpl11
-rw-r--r--template/en/default/attachment/diff-footer.html.tmpl6
-rw-r--r--template/en/default/attachment/diff-header.html.tmpl19
-rw-r--r--template/en/default/attachment/edit.html.tmpl13
-rw-r--r--template/en/default/attachment/list.html.tmpl10
-rw-r--r--template/en/default/bug/comments.html.tmpl143
-rw-r--r--template/en/default/bug/create/comment-guided.txt.tmpl2
-rw-r--r--template/en/default/bug/create/create-guided.html.tmpl48
-rw-r--r--template/en/default/bug/create/create.html.tmpl466
-rw-r--r--template/en/default/bug/edit.html.tmpl450
-rw-r--r--template/en/default/bug/field.html.tmpl29
-rw-r--r--template/en/default/bug/navigate.html.tmpl14
-rw-r--r--template/en/default/bug/process/bugmail.html.tmpl31
-rw-r--r--template/en/default/bug/process/updates-disabled.html.tmpl73
-rw-r--r--template/en/default/bug/show-header.html.tmpl35
-rw-r--r--template/en/default/bug/show-multiple.html.tmpl2
-rw-r--r--template/en/default/bug/show.xml.tmpl5
-rw-r--r--template/en/default/bug/time.html.tmpl8
-rw-r--r--template/en/default/config.rdf.tmpl4
-rw-r--r--template/en/default/email/bugmail-header.txt.tmpl18
-rw-r--r--template/en/default/email/bugmail.html.tmpl17
-rw-r--r--template/en/default/email/bugmail.txt.tmpl9
-rw-r--r--template/en/default/email/header-common.txt.tmpl24
-rw-r--r--template/en/default/email/lockout.txt.tmpl4
-rw-r--r--template/en/default/filterexceptions.pl6
-rw-r--r--template/en/default/flag/list.html.tmpl195
-rw-r--r--template/en/default/global/code-error.html.tmpl42
-rw-r--r--template/en/default/global/common-links.html.tmpl2
-rw-r--r--template/en/default/global/field-descs.none.tmpl4
-rw-r--r--template/en/default/global/footer.html.tmpl2
-rw-r--r--template/en/default/global/header.html.tmpl44
-rw-r--r--template/en/default/global/setting-descs.none.tmpl2
-rw-r--r--template/en/default/global/user-error.html.tmpl60
-rw-r--r--template/en/default/global/user.html.tmpl4
-rw-r--r--template/en/default/index.html.tmpl38
-rw-r--r--template/en/default/list/edit-multiple.html.tmpl7
-rw-r--r--template/en/default/list/list.html.tmpl21
-rw-r--r--template/en/default/list/table.html.tmpl80
-rw-r--r--template/en/default/pages/bugzilla.dtd.tmpl179
-rw-r--r--template/en/default/pages/fields.html.tmpl61
-rw-r--r--template/en/default/pages/quicksearch.html.tmpl8
-rw-r--r--template/en/default/reports/components.html.tmpl11
-rw-r--r--template/en/default/reports/report.html.tmpl4
-rw-r--r--template/en/default/request/email.txt.tmpl7
-rw-r--r--template/en/default/request/queue.html.tmpl23
-rw-r--r--template/en/default/search/boolean-charts.html.tmpl15
-rw-r--r--template/en/default/search/field.html.tmpl2
-rw-r--r--template/en/default/search/form.html.tmpl1
-rw-r--r--template/en/default/search/search-google.html.tmpl57
-rw-r--r--template/en/default/search/search-instant.html.tmpl85
-rw-r--r--template/en/default/search/search-specific.html.tmpl11
-rw-r--r--template/en/default/search/tabs.html.tmpl8
-rwxr-xr-xuserprefs.cgi45
-rwxr-xr-xwhine.pl9
-rwxr-xr-xxml.cgi41
-rw-r--r--xt/lib/Bugzilla/Test/Search/FieldTest.pm11
1435 files changed, 62367 insertions, 1739 deletions
diff --git a/.bzrignore b/.bzrignore
index 7ab83e7ad..e009f01c8 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -6,7 +6,6 @@
/docs/en/txt
/docs/en/html
/docs/en/pdf
-/skins/custom
/graphs
/data
/localconfig
diff --git a/.htaccess b/.htaccess
index c16ee19af..20eb372e8 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,5 +1,5 @@
# Don't allow people to retrieve non-cgi executable files or our private data
-<FilesMatch (\.pm|\.pl|\.tmpl|localconfig.*)$>
+<FilesMatch (\.pm|\.pl|\.tmpl|\.swf|localconfig.*)$>
deny from all
</FilesMatch>
<IfModule mod_expires.c>
@@ -23,3 +23,36 @@
</IfModule>
</IfModule>
</IfModule>
+
+AddType image/x-icon .ico
+ErrorDocument 401 /errors/401.html
+ErrorDocument 403 /errors/403.html
+ErrorDocument 404 /errors/404.html
+ErrorDocument 500 /errors/500.html
+
+Redirect permanent /queryhelp.cgi https://bugzilla.mozilla.org/query.cgi?format=advanced&help=1
+Redirect permanent /bug_status.html https://bugzilla.mozilla.org/page.cgi?id=fields.html
+Redirect permanent /bugwritinghelp.html https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html
+Redirect permanent /etiquette.html https://bugzilla.mozilla.org/page.cgi?id=etiquette.html
+Redirect permanent /duplicates.html https://bugzilla.mozilla.org/duplicates.cgi
+
+RewriteEngine On
+RewriteRule ^review(.*) page.cgi?id=splinter.html$1 [QSA]
+RewriteRule ^favicon\.ico$ extensions/BMO/web/images/favicon.ico
+RewriteRule ^form[\.:](itrequest|mozlist|poweredby|presentation|trademark|recoverykey)$ enter_bug.cgi?product=mozilla.org&format=$1
+RewriteRule ^form[\.:]legal$ enter_bug.cgi?product=Legal&format=legal
+RewriteRule ^form[\.:]mozpr$ enter_bug.cgi?product=Mozilla+PR&format=mozpr
+RewriteRule ^form[\.:]reps[\.:]mentorship$ enter_bug.cgi?product=Mozilla+Reps&format=mozreps
+RewriteRule ^form[\.:]reps[\.:]budget$ enter_bug.cgi?product=Mozilla+Reps&format=remo-budget
+RewriteRule ^form[\.:]reps[\.:]swag$ enter_bug.cgi?product=Mozilla+Reps&format=remo-swag
+RewriteRule ^form[\.:]reps[\.:]payment$ page.cgi?id=remo-form-payment.html
+RewriteRule ^form[\.:]employee[\.\-:]incident$ enter_bug.cgi?product=mozilla.org&format=employee-incident
+RewriteRule ^form[\.:]brownbag$ enter_bug.cgi?product=Air+Mozilla&format=brownbag
+RewriteRule ^form[\.:]finance$ enter_bug.cgi?product=Finance&format=finance
+RewriteRule ^form[\.:]privacy[\.\-:]data$ enter_bug.cgi?product=Privacy&format=privacy-data
+RewriteRule ^form[\.:]moz[\.\-:]project[\.\-:]review$ enter_bug.cgi?product=mozilla.org&format=moz-project-review
+RewriteRule ^form[\.:]docs?$ enter_bug.cgi?product=Developer+Documentation&format=doc [QSA]
+RewriteRule ^form[\.:]mdn?$ enter_bug.cgi?product=Mozilla+Developer+Network&format=mdn
+RewriteRule ^form[\.:](swag|gear)$ enter_bug.cgi?product=mozilla.org&format=swag
+RewriteRule ^form[\.:]b2g[\.:]partner enter_bug.cgi?product=Boot2Gecko&format=bootgecko-partner [QSA]
+RewriteRule ^form[\.:]ipp$ enter_bug.cgi?product=Internet+Public+Policy&format=ipp
diff --git a/Bugzilla.pm b/Bugzilla.pm
index 5b39e4c81..94c9ee9b8 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -35,6 +35,8 @@ BEGIN {
}
}
+# FIXME to remove later
+
use Bugzilla::Config;
use Bugzilla::Constants;
use Bugzilla::Auth;
@@ -42,9 +44,10 @@ use Bugzilla::Auth::Persist::Cookie;
use Bugzilla::CGI;
use Bugzilla::Extension;
use Bugzilla::DB;
+use Bugzilla::Hook;
use Bugzilla::Install::Localconfig qw(read_localconfig);
use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES);
-use Bugzilla::Install::Util qw(init_console);
+use Bugzilla::Install::Util qw(init_console include_languages);
use Bugzilla::Template;
use Bugzilla::User;
use Bugzilla::Error;
@@ -193,9 +196,7 @@ sub init_page {
#####################################################################
sub template {
- my $class = shift;
- $class->request_cache->{template} ||= Bugzilla::Template->create();
- return $class->request_cache->{template};
+ return $_[0]->request_cache->{template} ||= Bugzilla::Template->create();
}
sub template_inner {
@@ -203,9 +204,7 @@ sub template_inner {
my $cache = $class->request_cache;
my $current_lang = $cache->{template_current_lang}->[0];
$lang ||= $current_lang || '';
- $class->request_cache->{"template_inner_$lang"}
- ||= Bugzilla::Template->create(language => $lang);
- return $class->request_cache->{"template_inner_$lang"};
+ return $cache->{"template_inner_$lang"} ||= Bugzilla::Template->create(language => $lang);
}
our $extension_packages;
@@ -264,9 +263,7 @@ sub feature {
}
sub cgi {
- my $class = shift;
- $class->request_cache->{cgi} ||= new Bugzilla::CGI();
- return $class->request_cache->{cgi};
+ return $_[0]->request_cache->{cgi} ||= new Bugzilla::CGI();
}
sub input_params {
@@ -286,21 +283,15 @@ sub input_params {
}
sub localconfig {
- my $class = shift;
- $class->request_cache->{localconfig} ||= read_localconfig();
- return $class->request_cache->{localconfig};
+ return $_[0]->process_cache->{localconfig} ||= read_localconfig();
}
sub params {
- my $class = shift;
- $class->request_cache->{params} ||= Bugzilla::Config::read_param_file();
- return $class->request_cache->{params};
+ return $_[0]->request_cache->{params} ||= Bugzilla::Config::read_param_file();
}
sub user {
- my $class = shift;
- $class->request_cache->{user} ||= new Bugzilla::User;
- return $class->request_cache->{user};
+ return $_[0]->request_cache->{user} ||= new Bugzilla::User;
}
sub set_user {
@@ -309,8 +300,7 @@ sub set_user {
}
sub sudoer {
- my $class = shift;
- return $class->request_cache->{sudoer};
+ return $_[0]->request_cache->{sudoer};
}
sub sudo_request {
@@ -426,31 +416,27 @@ sub logout_request {
}
sub job_queue {
- my $class = shift;
require Bugzilla::JobQueue;
- $class->request_cache->{job_queue} ||= Bugzilla::JobQueue->new();
- return $class->request_cache->{job_queue};
+ return $_[0]->request_cache->{job_queue} ||= Bugzilla::JobQueue->new();
}
sub dbh {
- my $class = shift;
# If we're not connected, then we must want the main db
- $class->request_cache->{dbh} ||= $class->dbh_main;
-
- return $class->request_cache->{dbh};
+ return $_[0]->request_cache->{dbh} ||= $_[0]->dbh_main;
}
sub dbh_main {
- my $class = shift;
- $class->request_cache->{dbh_main} ||= Bugzilla::DB::connect_main();
- return $class->request_cache->{dbh_main};
+ return $_[0]->request_cache->{dbh_main} ||= Bugzilla::DB::connect_main();
}
sub languages {
- my $class = shift;
return Bugzilla::Install::Util::supported_languages();
}
+sub current_language {
+ return $_[0]->request_cache->{current_language} ||= (include_languages())[0];
+}
+
sub error_mode {
my ($class, $newval) = @_;
if (defined $newval) {
@@ -597,12 +583,20 @@ sub fields {
}
sub active_custom_fields {
- my $class = shift;
- if (!exists $class->request_cache->{active_custom_fields}) {
- $class->request_cache->{active_custom_fields} =
- Bugzilla::Field->match({ custom => 1, obsolete => 0 });
+ my ($class, $params) = @_;
+ my $cache_id = 'active_custom_fields';
+ if ($params) {
+ $cache_id .= ($params->{product} ? '_p' . $params->{product}->id : '') .
+ ($params->{component} ? '_c' . $params->{component}->id : '') .
+ ($params->{type} ? '_t' . $params->{type} : '');
+ }
+ if (!exists $class->request_cache->{$cache_id}) {
+ my $fields = Bugzilla::Field->match({ custom => 1, obsolete => 0});
+ Bugzilla::Hook::process('active_custom_fields',
+ { fields => \$fields, params => $params });
+ $class->request_cache->{$cache_id} = $fields;
}
- return @{$class->request_cache->{active_custom_fields}};
+ return @{$class->request_cache->{$cache_id}};
}
sub has_flags {
@@ -615,13 +609,8 @@ sub has_flags {
}
sub local_timezone {
- my $class = shift;
-
- if (!defined $class->request_cache->{local_timezone}) {
- $class->request_cache->{local_timezone} =
- DateTime::TimeZone->new(name => 'local');
- }
- return $class->request_cache->{local_timezone};
+ return $_[0]->process_cache->{local_timezone}
+ ||= DateTime::TimeZone->new(name => 'local');
}
# This creates the request cache for non-mod_perl installations.
@@ -642,6 +631,27 @@ sub request_cache {
return $_request_cache;
}
+sub clear_request_cache {
+ $_request_cache = {};
+ if ($ENV{MOD_PERL}) {
+ require Apache2::RequestUtil;
+ my $request = eval { Apache2::RequestUtil->request };
+ if ($request) {
+ my $pnotes = $request->pnotes;
+ delete @$pnotes{(keys %$pnotes)};
+ }
+ }
+}
+
+# This is a per-process cache. Under mod_cgi it's identical to the
+# request_cache. When using mod_perl, items in this cache live until the
+# worker process is terminated.
+our $_process_cache = {};
+
+sub process_cache {
+ return $_process_cache;
+}
+
# Private methods
# Per-process cleanup. Note that this is a plain subroutine, not a method,
@@ -654,7 +664,7 @@ sub _cleanup {
$dbh->bz_rollback_transaction() if $dbh->bz_in_transaction;
$dbh->disconnect;
}
- undef $_request_cache;
+ clear_request_cache();
# These are both set by CGI.pm but need to be undone so that
# Apache can actually shut down its children if it needs to.
@@ -915,6 +925,10 @@ The main database handle. See L<DBI>.
Currently installed languages.
Returns a reference to a list of RFC 1766 language tags of installed languages.
+=item C<current_language>
+
+The currently active language.
+
=item C<switch_to_shadow_db>
Switch from using the main database to using the shadow database.
diff --git a/Bugzilla/Arecibo.pm b/Bugzilla/Arecibo.pm
new file mode 100644
index 000000000..08ff11c20
--- /dev/null
+++ b/Bugzilla/Arecibo.pm
@@ -0,0 +1,301 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Arecibo;
+
+use strict;
+use warnings;
+
+use base qw(Exporter);
+our @EXPORT = qw(
+ arecibo_handle_error
+ arecibo_generate_id
+ arecibo_should_notify
+);
+
+use Apache2::Log;
+use Apache2::SubProcess;
+use Carp;
+use Data::Dumper;
+use Email::Date::Format qw(email_gmdate);
+use File::Temp;
+use LWP::UserAgent;
+use Sys::Hostname;
+
+use Bugzilla::Constants;
+use Bugzilla::Util;
+use Bugzilla::WebService::Constants;
+
+use constant CONFIG => {
+ # 'types' maps from the error message to types and priorities
+ types => [
+ {
+ type => 'the_schwartz',
+ boost => -10,
+ match => [
+ qr/TheSchwartz\.pm/,
+ ],
+ },
+ {
+ type => 'database_error',
+ boost => -10,
+ match => [
+ qr/DBD::mysql/,
+ qr/Can't connect to the database/,
+ ],
+ },
+ {
+ type => 'patch_reader',
+ boost => +5,
+ match => [
+ qr#/PatchReader/#,
+ ],
+ },
+ {
+ type => 'uninitialized_warning',
+ boost => 0,
+ match => [
+ qr/Use of uninitialized value/,
+ ],
+ },
+ ],
+
+ # 'codes' lists the code-errors which are sent to arecibo
+ codes => [qw(
+ bug_error
+ chart_datafile_corrupt
+ chart_dir_nonexistent
+ chart_file_open_fail
+ illegal_content_type_method
+ jobqueue_insert_failed
+ ldap_bind_failed
+ mail_send_error
+ template_error
+ token_generation_error
+ )],
+
+ # any error messages matching these regex's will not be sent to arecibo
+ ignore => [
+ qr/Software caused connection abort/,
+ qr/Could not check out .*\/cvsroot/,
+ ],
+};
+
+sub arecibo_generate_id {
+ return sprintf("%s.%s", (time), $$);
+}
+
+sub arecibo_should_notify {
+ my $code_error = shift;
+ return grep { $_ eq $code_error } @{CONFIG->{codes}};
+}
+
+sub arecibo_handle_error {
+ my $class = shift;
+ my @message = split(/\n/, shift);
+ my $id = arecibo_generate_id();
+
+ my $is_error = $class eq 'error';
+ if ($class ne 'error' && $class ne 'warning') {
+ # it's a code-error
+ return 0 unless arecibo_should_notify($class);
+ $is_error = 1;
+ }
+
+ # build traceback
+ my $traceback;
+ {
+ # for now don't show function arguments, in case they contain
+ # confidential data. waiting on bug 700683
+ #local $Carp::MaxArgLen = 256;
+ #local $Carp::MaxArgNums = 0;
+ local $Carp::MaxArgNums = -1;
+ local $Carp::CarpInternal{'CGI::Carp'} = 1;
+ local $Carp::CarpInternal{'Bugzilla::Error'} = 1;
+ local $Carp::CarpInternal{'Bugzilla::Arecibo'} = 1;
+ $traceback = Carp::longmess();
+ }
+
+ # strip timestamp
+ foreach my $line (@message) {
+ $line =~ s/^\[[^\]]+\] //;
+ }
+ my $message = join(" ", map { trim($_) } grep { $_ ne '' } @message);
+
+ # don't send to arecibo unless configured
+ my $arecibo_server = Bugzilla->params->{arecibo_server} || '';
+ my $send_to_arecibo = $arecibo_server ne '';
+
+ # web service filtering
+ if ($send_to_arecibo
+ && (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT || Bugzilla->error_mode == ERROR_MODE_JSON_RPC))
+ {
+ my ($code) = $message =~ /^(-?\d+): /;
+ if ($code
+ && !($code == ERROR_UNKNOWN_FATAL || $code == ERROR_UNKNOWN_TRANSIENT))
+ {
+ $send_to_arecibo = 0;
+ }
+ }
+
+ # message content filtering
+ if ($send_to_arecibo) {
+ foreach my $re (@{CONFIG->{ignore}}) {
+ if ($message =~ $re) {
+ $send_to_arecibo = 0;
+ last;
+ }
+ }
+ }
+
+ # log to apache's error_log
+ if ($send_to_arecibo) {
+ $message .= " [#$id]";
+ } else {
+ $traceback =~ s/\n/ /g;
+ $message .= " $traceback";
+ }
+ _write_to_error_log($message, $is_error);
+
+ return 0 unless $send_to_arecibo;
+
+ # set the error type and priority from the message content
+ $message = join("\n", grep { $_ ne '' } @message);
+ my $type = '';
+ my $priority = $class eq 'error' ? 3 : 10;
+ foreach my $rh_type (@{CONFIG->{types}}) {
+ foreach my $re (@{$rh_type->{match}}) {
+ if ($message =~ $re) {
+ $type = $rh_type->{type};
+ $priority += $rh_type->{boost};
+ last;
+ }
+ }
+ last if $type ne '';
+ }
+ $type ||= $class;
+ $priority = 1 if $priority < 1;
+ $priority = 10 if $priority > 10;
+
+ my $username = '';
+ eval { $username = Bugzilla->user->login };
+
+ my $request = '';
+ foreach my $name (sort { lc($a) cmp lc($b) } keys %ENV) {
+ $request .= "$name=$ENV{$name}\n";
+ }
+ chomp($request);
+
+ my $data = [
+ ip => remote_ip(),
+ msg => $message,
+ priority => $priority,
+ server => hostname(),
+ request => $request,
+ status => '500',
+ timestamp => email_gmdate(),
+ traceback => $traceback,
+ type => $type,
+ uid => $id,
+ url => Bugzilla->cgi->self_url,
+ user_agent => $ENV{HTTP_USER_AGENT},
+ username => $username,
+ ];
+
+ my $fh = File::Temp->new( UNLINK => 0 );
+ if (!$fh) {
+ warn "Failed to create temp file: $!\n";
+ return;
+ }
+ print $fh Dumper($data);
+ close($fh) or die $!;
+ my $filename = $fh->filename;
+
+ my $command = bz_locations()->{'cgi_path'} . "/arecibo.pl '$filename' &";
+ system($command);
+ return 1;
+}
+
+sub _write_to_error_log {
+ my ($message, $is_error) = @_;
+ if ($ENV{MOD_PERL}) {
+ if ($is_error) {
+ Apache2::ServerRec::log_error($message);
+ } else {
+ Apache2::ServerRec::warn($message);
+ }
+ } else {
+ print STDERR "$message\n";
+ }
+}
+
+# lifted from Bugzilla::Error
+sub _in_eval {
+ my $in_eval = 0;
+ for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
+ last if $sub =~ /^ModPerl/;
+ last if $sub =~ /^Bugzilla::Template/;
+ $in_eval = 1 if $sub =~ /^\(eval\)/;
+ }
+ return $in_eval;
+}
+
+sub _arecibo_die_handler {
+ my $message = shift;
+ $message =~ s/^undef error - //;
+
+ # avoid recursion, and check for CGI::Carp::die failures
+ my $in_cgi_carp_die = 0;
+ for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
+ return if $sub =~ /:_arecibo_die_handler$/;
+ $in_cgi_carp_die = 1 if $sub =~ /CGI::Carp::die$/;
+ }
+
+ return if _in_eval();
+
+ # mod_perl overrides exit to call die with this string
+ exit if $message =~ /\bModPerl::Util::exit\b/;
+
+ my $nested_error = '';
+ my $is_compilation_failure = $message =~ /\bcompilation (aborted|failed)\b/i;
+
+ # if we are called via CGI::Carp::die chances are something is seriously
+ # wrong, so skip trying to use ThrowTemplateError
+ if (!$in_cgi_carp_die && !$is_compilation_failure) {
+ eval { Bugzilla::Error::ThrowTemplateError($message) };
+ $nested_error = $@ if $@;
+ }
+
+ if ($is_compilation_failure ||
+ $in_cgi_carp_die ||
+ ($nested_error && $nested_error !~ /\bModPerl::Util::exit\b/)
+ ) {
+ arecibo_handle_error('error', $message);
+
+ # and call the normal error management
+ # (ISE for web pages, error response for web services, etc)
+ CORE::die($message);
+ }
+ exit;
+}
+
+sub install_arecibo_handler {
+ require CGI::Carp;
+ CGI::Carp::set_die_handler(\&_arecibo_die_handler);
+ $main::SIG{__WARN__} = sub {
+ return if _in_eval();
+ arecibo_handle_error('warning', shift);
+ };
+}
+
+BEGIN {
+ if ($ENV{SCRIPT_NAME} || $ENV{MOD_PERL}) {
+ install_arecibo_handler();
+ }
+}
+
+1;
diff --git a/Bugzilla/Attachment.pm b/Bugzilla/Attachment.pm
index 69939a657..094406c91 100644
--- a/Bugzilla/Attachment.pm
+++ b/Bugzilla/Attachment.pm
@@ -160,7 +160,7 @@ sub bug {
my $self = shift;
require Bugzilla::Bug;
- $self->{bug} ||= Bugzilla::Bug->new($self->bug_id);
+ $self->{bug} ||= Bugzilla::Bug->new({ id => $self->bug_id, cache => 1 });
return $self->{bug};
}
@@ -415,6 +415,53 @@ sub datasize {
return $self->{datasize};
}
+=over
+
+=item C<linecount>
+
+the number of lines of the attachment content
+
+=back
+
+=cut
+
+# linecount allows for getting the number of lines of an attachment
+# from the database directly if the data has not yet been loaded for
+# performance reasons.
+
+sub linecount {
+ my ($self) = @_;
+
+ return $self->{linecount} if exists $self->{linecount};
+
+ # Limit this to just text/* attachments as this could
+ # cause strange results for binary attachments.
+ return if $self->contenttype !~ /^text\//;
+
+ # If the data has already been loaded, we can just determine
+ # line count from the data directly.
+ if ($self->{data}) {
+ $self->{linecount} = $self->{data} =~ tr/\n/\n/;
+ }
+ else {
+ $self->{linecount} =
+ int(Bugzilla->dbh->selectrow_array("
+ SELECT LENGTH(attach_data.thedata)-LENGTH(REPLACE(attach_data.thedata,'\n',''))/LENGTH('\n')
+ FROM attach_data WHERE id = ?", undef, $self->id));
+
+ }
+
+ # If we still do not have a linecount either the attachment
+ # is stored in a local file or has been deleted. If the former,
+ # we call self->data to force a load from the filesystem and
+ # then do a split on newlines and count again.
+ unless ($self->{linecount}) {
+ $self->{linecount} = $self->data =~ tr/\n/\n/;
+ }
+
+ return $self->{linecount};
+}
+
sub _get_local_filename {
my $self = shift;
my $hash = ($self->id % 100) + 100;
@@ -458,7 +505,8 @@ sub flag_types {
my $vars = { target_type => 'attachment',
product_id => $self->bug->product_id,
component_id => $self->bug->component_id,
- attach_id => $self->id };
+ attach_id => $self->id,
+ active_or_has_flags => $self->bug_id };
$self->{flag_types} = Bugzilla::Flag->_flag_types($vars);
return $self->{flag_types};
diff --git a/Bugzilla/Attachment/PatchReader.pm b/Bugzilla/Attachment/PatchReader.pm
index cfc7610f4..049487b68 100644
--- a/Bugzilla/Attachment/PatchReader.pm
+++ b/Bugzilla/Attachment/PatchReader.pm
@@ -19,6 +19,9 @@ use strict;
package Bugzilla::Attachment::PatchReader;
+use IPC::Open3;
+use Symbol 'gensym';
+
use Bugzilla::Error;
use Bugzilla::Attachment;
use Bugzilla::Util;
@@ -33,8 +36,8 @@ sub process_diff {
my ($reader, $last_reader) = setup_patch_readers(undef, $context);
if ($format eq 'raw') {
- require PatchReader::DiffPrinter::raw;
- $last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
+ require Bugzilla::PatchReader::DiffPrinter::raw;
+ $last_reader->sends_data_to(new Bugzilla::PatchReader::DiffPrinter::raw());
# Actually print out the patch.
print $cgi->header(-type => 'text/plain',
-expires => '+3M');
@@ -109,13 +112,37 @@ sub process_interdiff {
# Send through interdiff, send output directly to template.
# Must hack path so that interdiff will work.
$ENV{'PATH'} = $lc->{diffpath};
- open my $interdiff_fh, "$lc->{interdiffbin} $old_filename $new_filename|";
- binmode $interdiff_fh;
+
+ my ($pid, $interdiff_stdout, $interdiff_stderr);
+ if ($ENV{MOD_PERL}) {
+ require Apache2::RequestUtil;
+ require Apache2::SubProcess;
+ my $request = Apache2::RequestUtil->request;
+ (undef, $interdiff_stdout, $interdiff_stderr) = $request->spawn_proc_prog(
+ $lc->{interdiffbin}, [$old_filename, $new_filename]
+ );
+ } else {
+ $interdiff_stderr = gensym;
+ my $pid = open3(gensym, $interdiff_stdout, $interdiff_stderr,
+ $lc->{interdiffbin}, $old_filename, $new_filename);
+ }
+ binmode $interdiff_stdout;
+
+ # Check for errors
+ {
+ local $/ = undef;
+ my $error = <$interdiff_stderr>;
+ if ($error) {
+ warn($error);
+ $warning = 'interdiff3';
+ }
+ }
+
my ($reader, $last_reader) = setup_patch_readers("", $context);
if ($format eq 'raw') {
- require PatchReader::DiffPrinter::raw;
- $last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
+ require Bugzilla::PatchReader::DiffPrinter::raw;
+ $last_reader->sends_data_to(new Bugzilla::PatchReader::DiffPrinter::raw());
# Actually print out the patch.
print $cgi->header(-type => 'text/plain',
-expires => '+3M');
@@ -123,7 +150,7 @@ sub process_interdiff {
}
else {
# In case the HTML page is displayed with the UTF-8 encoding.
- binmode $interdiff_fh, ':utf8' if Bugzilla->params->{'utf8'};
+ binmode $interdiff_stdout, ':utf8' if Bugzilla->params->{'utf8'};
$vars->{'warning'} = $warning if $warning;
$vars->{'bugid'} = $new_attachment->bug_id;
@@ -134,9 +161,9 @@ sub process_interdiff {
setup_template_patch_reader($last_reader, $format, $context, $vars);
}
- $reader->iterate_fh($interdiff_fh, 'interdiff #' . $old_attachment->id .
+ $reader->iterate_fh($interdiff_stdout, 'interdiff #' . $old_attachment->id .
' #' . $new_attachment->id);
- close $interdiff_fh;
+ waitpid($pid, 0) if $pid;
$ENV{'PATH'} = '';
# Delete temporary files.
@@ -152,29 +179,29 @@ sub get_unified_diff {
my ($attachment, $format) = @_;
# Bring in the modules we need.
- require PatchReader::Raw;
- require PatchReader::FixPatchRoot;
- require PatchReader::DiffPrinter::raw;
- require PatchReader::PatchInfoGrabber;
+ require Bugzilla::PatchReader::Raw;
+ require Bugzilla::PatchReader::FixPatchRoot;
+ require Bugzilla::PatchReader::DiffPrinter::raw;
+ require Bugzilla::PatchReader::PatchInfoGrabber;
require File::Temp;
$attachment->ispatch
|| ThrowCodeError('must_be_patch', { 'attach_id' => $attachment->id });
# Reads in the patch, converting to unified diff in a temp file.
- my $reader = new PatchReader::Raw;
+ my $reader = new Bugzilla::PatchReader::Raw;
my $last_reader = $reader;
# Fixes patch root (makes canonical if possible).
if (Bugzilla->params->{'cvsroot'}) {
my $fix_patch_root =
- new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'});
+ new Bugzilla::PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'});
$last_reader->sends_data_to($fix_patch_root);
$last_reader = $fix_patch_root;
}
# Grabs the patch file info.
- my $patch_info_grabber = new PatchReader::PatchInfoGrabber();
+ my $patch_info_grabber = new Bugzilla::PatchReader::PatchInfoGrabber();
$last_reader->sends_data_to($patch_info_grabber);
$last_reader = $patch_info_grabber;
@@ -184,7 +211,7 @@ sub get_unified_diff {
# The HTML page will be displayed with the UTF-8 encoding.
binmode $fh, ':utf8';
}
- my $raw_printer = new PatchReader::DiffPrinter::raw($fh);
+ my $raw_printer = new Bugzilla::PatchReader::DiffPrinter::raw($fh);
$last_reader->sends_data_to($raw_printer);
$last_reader = $raw_printer;
@@ -228,13 +255,13 @@ sub setup_patch_readers {
# Define the patch readers.
# The reader that reads the patch in (whatever its format).
- require PatchReader::Raw;
- my $reader = new PatchReader::Raw;
+ require Bugzilla::PatchReader::Raw;
+ my $reader = new Bugzilla::PatchReader::Raw;
my $last_reader = $reader;
# Fix the patch root if we have a cvs root.
if (Bugzilla->params->{'cvsroot'}) {
- require PatchReader::FixPatchRoot;
- $last_reader->sends_data_to(new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'}));
+ require Bugzilla::PatchReader::FixPatchRoot;
+ $last_reader->sends_data_to(new Bugzilla::PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'}));
$last_reader->sends_data_to->diff_root($diff_root) if defined($diff_root);
$last_reader = $last_reader->sends_data_to;
}
@@ -243,12 +270,12 @@ sub setup_patch_readers {
if ($context ne 'patch' && Bugzilla->localconfig->{cvsbin}
&& Bugzilla->params->{'cvsroot_get'})
{
- require PatchReader::AddCVSContext;
+ require Bugzilla::PatchReader::AddCVSContext;
# We need to set $cvsbin as global, because PatchReader::CVSClient
# needs it in order to find 'cvs'.
$main::cvsbin = Bugzilla->localconfig->{cvsbin};
$last_reader->sends_data_to(
- new PatchReader::AddCVSContext($context, Bugzilla->params->{'cvsroot_get'}));
+ new Bugzilla::PatchReader::AddCVSContext($context, Bugzilla->params->{'cvsroot_get'}));
$last_reader = $last_reader->sends_data_to;
}
@@ -260,7 +287,7 @@ sub setup_template_patch_reader {
my $cgi = Bugzilla->cgi;
my $template = Bugzilla->template;
- require PatchReader::DiffPrinter::template;
+ require Bugzilla::PatchReader::DiffPrinter::template;
# Define the vars for templates.
if (defined $cgi->param('headers')) {
@@ -279,7 +306,7 @@ sub setup_template_patch_reader {
print $cgi->header(-type => 'text/html',
-expires => '+3M');
- $last_reader->sends_data_to(new PatchReader::DiffPrinter::template($template,
+ $last_reader->sends_data_to(new Bugzilla::PatchReader::DiffPrinter::template($template,
"attachment/diff-header.$format.tmpl",
"attachment/diff-file.$format.tmpl",
"attachment/diff-footer.$format.tmpl",
diff --git a/Bugzilla/Auth.pm b/Bugzilla/Auth.pm
index 45034e166..ab741965a 100644
--- a/Bugzilla/Auth.pm
+++ b/Bugzilla/Auth.pm
@@ -38,6 +38,7 @@ use Bugzilla::User::Setting ();
use Bugzilla::Auth::Login::Stack;
use Bugzilla::Auth::Verify::Stack;
use Bugzilla::Auth::Persist::Cookie;
+use Socket;
sub new {
my ($class, $params) = @_;
@@ -215,10 +216,18 @@ sub _handle_login_result {
my $default_settings = Bugzilla::User::Setting::get_defaults();
my $template = Bugzilla->template_inner(
$default_settings->{lang}->{default_value});
+ my $address = $attempts->[0]->{ip_addr};
+ # Note: inet_aton will only resolve IPv4 addresses.
+ # For IPv6 we'll need to use inet_pton which requires Perl 5.12.
+ my $n = inet_aton($address);
+ if ($n) {
+ $address = gethostbyaddr($n, AF_INET) . " ($address)"
+ }
my $vars = {
locked_user => $user,
attempts => $attempts,
unlock_at => $unlock_at,
+ address => $address,
};
my $message;
$template->process('email/lockout.txt.tmpl', $vars, \$message)
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
index 7b86ab2a1..08c347abe 100644
--- a/Bugzilla/Bug.pm
+++ b/Bugzilla/Bug.pm
@@ -333,10 +333,14 @@ sub new {
# If we get something that looks like a word (not a number),
# make it the "name" param.
- if (!defined $param || (!ref($param) && $param !~ /^\d+$/)) {
+ if (!defined $param
+ || (!ref($param) && (!$param || $param =~ /\D/))
+ || (ref($param) && (!$param->{id} || $param->{id} =~ /\D/)))
+ {
# But only if aliases are enabled.
if (Bugzilla->params->{'usebugaliases'} && $param) {
- $param = { name => $param };
+ $param = { name => ref($param) ? $param->{id} : $param,
+ cache => ref($param) ? $param->{cache} : 0 };
}
else {
# Aliases are off, and we got something that's not a number.
@@ -370,20 +374,31 @@ sub new {
return $self;
}
-sub check {
+sub cache_key {
my $class = shift;
- my ($id, $field) = @_;
+ my $key = $class->SUPER::cache_key(@_)
+ || return;
+ return $key . ',' . Bugzilla->user->id;
+}
- ThrowUserError('improper_bug_id_field_value', { field => $field }) unless defined $id;
+sub check {
+ my $class = shift;
+ my ($param, $field) = @_;
# Bugzilla::Bug throws lots of special errors, so we don't call
# SUPER::check, we just call our new and do our own checks.
- my $self = $class->new(trim($id));
- # For error messages, use the id that was returned by new(), because
- # it's cleaned up.
- $id = $self->id;
+ my $id = ref($param)
+ ? ($param->{id} = trim($param->{id}))
+ : ($param = trim($param));
+ ThrowUserError('improper_bug_id_field_value', { field => $field }) unless defined $id;
+
+ my $self = $class->new($param);
if ($self->{error}) {
+ # For error messages, use the id that was returned by new(), because
+ # it's cleaned up.
+ $id = $self->id;
+
if ($self->{error} eq 'NotFound') {
ThrowUserError("bug_id_does_not_exist", { bug_id => $id });
}
@@ -721,7 +736,7 @@ sub create {
# Because MySQL doesn't support transactions on the fulltext table,
# we do this after we've committed the transaction. That way we're
# sure we're inserting a good Bug ID.
- $bug->_sync_fulltext('new bug');
+ $bug->_sync_fulltext( new_bug => 1 );
return $bug;
}
@@ -775,8 +790,9 @@ sub run_create_validators {
sub update {
my $self = shift;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
- my $dbh = Bugzilla->dbh;
# XXX This is just a temporary hack until all updating happens
# inside this function.
my $delta_ts = shift || $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
@@ -785,6 +801,10 @@ sub update {
my ($changes, $old_bug) = $self->SUPER::update(@_);
+ Bugzilla::Hook::process('bug_start_of_update',
+ { timestamp => $delta_ts, bug => $self,
+ old_bug => $old_bug, changes => $changes });
+
# Certain items in $changes have to be fixed so that they hold
# a name instead of an ID.
foreach my $field (qw(product_id component_id)) {
@@ -863,7 +883,7 @@ sub update {
# Add an activity entry for the other bug.
LogActivityEntry($removed_id, $other, $self->id, '',
- Bugzilla->user->id, $delta_ts);
+ $user->id, $delta_ts);
# Update delta_ts on the other bug so that we trigger mid-airs.
$dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
undef, $delta_ts, $removed_id);
@@ -874,7 +894,7 @@ sub update {
# Add an activity entry for the other bug.
LogActivityEntry($added_id, $other, '', $self->id,
- Bugzilla->user->id, $delta_ts);
+ $user->id, $delta_ts);
# Update delta_ts on the other bug so that we trigger mid-airs.
$dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
undef, $delta_ts, $added_id);
@@ -922,7 +942,7 @@ sub update {
$comment = Bugzilla::Comment->insert_create_data($comment);
if ($comment->work_time) {
LogActivityEntry($self->id, "work_time", "", $comment->work_time,
- Bugzilla->user->id, $delta_ts);
+ $user->id, $delta_ts);
}
}
@@ -933,7 +953,7 @@ sub update {
my ($from, $to)
= $comment->is_private ? (0, 1) : (1, 0);
LogActivityEntry($self->id, "longdescs.isprivate", $from, $to,
- Bugzilla->user->id, $delta_ts, $comment->id);
+ $user->id, $delta_ts, $comment->id);
}
# Insert the values into the multiselect value tables
@@ -978,8 +998,8 @@ sub update {
my $change = $changes->{$field};
my $from = defined $change->[0] ? $change->[0] : '';
my $to = defined $change->[1] ? $change->[1] : '';
- LogActivityEntry($self->id, $field, $from, $to, Bugzilla->user->id,
- $delta_ts);
+ LogActivityEntry($self->id, $field, $from, $to,
+ $user->id, $delta_ts);
}
# Check if we have to update the duplicates table and the other bug.
@@ -993,7 +1013,7 @@ sub update {
$update_dup->update();
}
}
-
+
$changes->{'dup_id'} = [$old_dup || undef, $cur_dup || undef];
}
@@ -1010,15 +1030,35 @@ sub update {
$self->{delta_ts} = $delta_ts;
}
+ # Update bug ignore data if user wants to ignore mail for this bug
+ if (exists $self->{'bug_ignored'}) {
+ my $bug_ignored_changed;
+ if ($self->{'bug_ignored'} && !$user->is_bug_ignored($self->id)) {
+ $dbh->do('INSERT INTO email_bug_ignore
+ (user_id, bug_id) VALUES (?, ?)',
+ undef, $user->id, $self->id);
+ $bug_ignored_changed = 1;
+
+ }
+ elsif (!$self->{'bug_ignored'} && $user->is_bug_ignored($self->id)) {
+ $dbh->do('DELETE FROM email_bug_ignore
+ WHERE user_id = ? AND bug_id = ?',
+ undef, $user->id, $self->id);
+ $bug_ignored_changed = 1;
+ }
+ delete $user->{bugs_ignored} if $bug_ignored_changed;
+ }
+
$dbh->bz_commit_transaction();
# The only problem with this here is that update() is often called
# in the middle of a transaction, and if that transaction is rolled
# back, this change will *not* be rolled back. As we expect rollbacks
# to be extremely rare, that is OK for us.
- $self->_sync_fulltext()
- if $self->{added_comments} || $changes->{short_desc}
- || $self->{comment_isprivate};
+ $self->_sync_fulltext(
+ update_short_desc => $changes->{short_desc},
+ update_comments => $self->{added_comments} || $self->{comment_isprivate}
+ );
# Remove obsolete internal variables.
delete $self->{'_old_assigned_to'};
@@ -1026,7 +1066,7 @@ sub update {
# Also flush the visible_bugs cache for this bug as the user's
# relationship with this bug may have changed.
- delete Bugzilla->user->{_visible_bugs_cache}->{$self->id};
+ delete $user->{_visible_bugs_cache}->{$self->id};
return $changes;
}
@@ -1052,25 +1092,43 @@ sub _extract_multi_selects {
# Should be called any time you update short_desc or change a comment.
sub _sync_fulltext {
- my ($self, $new_bug) = @_;
+ my ($self, %options) = @_;
my $dbh = Bugzilla->dbh;
- if ($new_bug) {
- $dbh->do('INSERT INTO bugs_fulltext (bug_id, short_desc)
- SELECT bug_id, short_desc FROM bugs WHERE bug_id = ?',
- undef, $self->id);
+
+ my($all_comments, $public_comments);
+ if ($options{new_bug} || $options{update_comments}) {
+ my $comments = $dbh->selectall_arrayref(
+ 'SELECT thetext, isprivate FROM longdescs WHERE bug_id = ?',
+ undef, $self->id);
+ $all_comments = join("\n", map { $_->[0] } @$comments);
+ my @no_private = grep { !$_->[1] } @$comments;
+ $public_comments = join("\n", map { $_->[0] } @no_private);
}
- else {
- $dbh->do('UPDATE bugs_fulltext SET short_desc = ? WHERE bug_id = ?',
- undef, $self->short_desc, $self->id);
+
+ if ($options{new_bug}) {
+ $dbh->do('INSERT INTO bugs_fulltext (bug_id, short_desc, comments,
+ comments_noprivate)
+ VALUES (?, ?, ?, ?)',
+ undef,
+ $self->id, $self->short_desc, $all_comments, $public_comments);
+ } else {
+ my(@names, @values);
+ if ($options{update_short_desc}) {
+ push @names, 'short_desc';
+ push @values, $self->short_desc;
+ }
+ if ($options{update_comments}) {
+ push @names, ('comments', 'comments_noprivate');
+ push @values, ($all_comments, $public_comments);
+ }
+ if (@names) {
+ $dbh->do('UPDATE bugs_fulltext SET ' .
+ join(', ', map { "$_ = ?" } @names) .
+ ' WHERE bug_id = ?',
+ undef,
+ @values, $self->id);
+ }
}
- my $comments = $dbh->selectall_arrayref(
- 'SELECT thetext, isprivate FROM longdescs WHERE bug_id = ?',
- undef, $self->id);
- my $all = join("\n", map { $_->[0] } @$comments);
- my @no_private = grep { !$_->[1] } @$comments;
- my $nopriv_string = join("\n", map { $_->[0] } @no_private);
- $dbh->do('UPDATE bugs_fulltext SET comments = ?, comments_noprivate = ?
- WHERE bug_id = ?', undef, $all, $nopriv_string, $self->id);
}
@@ -1637,6 +1695,14 @@ sub _check_groups {
: $params->{product};
my %add_groups;
+ # BMO: Allow extension to add groups before the
+ # real checks are done.
+ Bugzilla::Hook::process('bug_check_groups', {
+ product => $product,
+ group_names => $group_names,
+ add_groups => \%add_groups
+ });
+
# In email or WebServices, when the "groups" item actually
# isn't specified, then just add the default groups.
if (!defined $group_names) {
@@ -1655,7 +1721,12 @@ sub _check_groups {
foreach my $name (@$group_names) {
my $group = Bugzilla::Group->check_no_disclose({ %args, name => $name });
- if (!$product->group_is_settable($group)) {
+ # BMO: Do not check group_is_settable if the group is
+ # already added, such as from the extension hook. group_is_settable
+ # will reject any group the user is not currently in.
+ if (!$add_groups{$group->id}
+ && !$product->group_is_settable($group))
+ {
ThrowUserError('group_restriction_not_allowed', { %args, name => $name });
}
$add_groups{$group->id} = $group;
@@ -1664,7 +1735,7 @@ sub _check_groups {
# Now enforce mandatory groups.
$add_groups{$_->id} = $_ foreach @{ $product->groups_mandatory };
-
+
my @add_groups = values %add_groups;
return \@add_groups;
}
@@ -2266,7 +2337,7 @@ sub set_all {
# we have to check that the current assignee, qa, and CCs are still
# valid if we've switched products, under strict_isolation. We can only
# do that here, because if they *did* change the assignee, qa, or CC,
- # then we don't want to check the original ones, only the new ones.
+ # then we don't want to check the original ones, only the new ones.
$self->_check_strict_isolation() if $product_changed;
}
@@ -2296,6 +2367,7 @@ sub reset_assigned_to {
my $comp = $self->component_obj;
$self->set_assigned_to($comp->default_assignee);
}
+sub set_bug_ignored { $_[0]->set('bug_ignored', $_[1]); }
sub set_cclist_accessible { $_[0]->set('cclist_accessible', $_[1]); }
sub set_comment_is_private {
my ($self, $comment_id, $isprivate) = @_;
@@ -3239,7 +3311,8 @@ sub component_obj {
my ($self) = @_;
return $self->{component_obj} if defined $self->{component_obj};
return {} if $self->{error};
- $self->{component_obj} = new Bugzilla::Component($self->{component_id});
+ $self->{component_obj} =
+ new Bugzilla::Component({ id => $self->{component_id}, cache => 1 });
return $self->{component_obj};
}
@@ -3278,6 +3351,26 @@ sub depends_on_obj {
return $self->{depends_on_obj};
}
+sub duplicates {
+ my $self = shift;
+ return $self->{duplicates} if exists $self->{duplicates};
+ return [] if $self->{error};
+ $self->{duplicates} = Bugzilla::Bug->new_from_list($self->duplicate_ids);
+ return $self->{duplicates};
+}
+
+sub duplicate_ids {
+ my $self = shift;
+ return $self->{duplicate_ids} if exists $self->{duplicate_ids};
+ return [] if $self->{error};
+
+ my $dbh = Bugzilla->dbh;
+ $self->{duplicate_ids} =
+ $dbh->selectcol_arrayref('SELECT dupe FROM duplicates WHERE dupe_of = ?',
+ undef, $self->id);
+ return $self->{duplicate_ids};
+}
+
sub flag_types {
my ($self) = @_;
return $self->{'flag_types'} if exists $self->{'flag_types'};
@@ -3286,7 +3379,8 @@ sub flag_types {
my $vars = { target_type => 'bug',
product_id => $self->{product_id},
component_id => $self->{component_id},
- bug_id => $self->bug_id };
+ bug_id => $self->bug_id,
+ active_or_has_flags => $self->bug_id };
$self->{'flag_types'} = Bugzilla::Flag->_flag_types($vars);
return $self->{'flag_types'};
@@ -3387,7 +3481,8 @@ sub product {
sub product_obj {
my $self = shift;
return {} if $self->{error};
- $self->{product_obj} ||= new Bugzilla::Product($self->{product_id});
+ $self->{product_obj} ||=
+ new Bugzilla::Product({ id => $self->{product_id}, cache => 1 });
return $self->{product_obj};
}
@@ -3805,14 +3900,26 @@ sub GetBugActivity {
$changes = [];
}
+ # If this is the same field as the previoius item, then concatenate
+ # the data into the same change.
+ if ($operation->{'who'} && $who eq $operation->{'who'}
+ && $when eq $operation->{'when'}
+ && $fieldname eq $operation->{'fieldname'}
+ && ($attachid || 0) == ($operation->{'attachid'} || 0))
+ {
+ my $old_change = pop @$changes;
+ $removed = _join_activity_entries($fieldname, $old_change->{'removed'}, $removed);
+ $added = _join_activity_entries($fieldname, $old_change->{'added'}, $added);
+ }
+
$operation->{'who'} = $who;
$operation->{'when'} = $when;
+ $operation->{'fieldname'} = $change{'fieldname'} = $fieldname;
+ $operation->{'attachid'} = $change{'attachid'} = $attachid;
- $change{'fieldname'} = $fieldname;
- $change{'attachid'} = $attachid;
$change{'removed'} = $removed;
$change{'added'} = $added;
-
+
if ($comment_id) {
$change{'comment'} = Bugzilla::Comment->new($comment_id);
}
@@ -3829,6 +3936,37 @@ sub GetBugActivity {
return(\@operations, $incomplete_data);
}
+sub _join_activity_entries {
+ my ($field, $current_change, $new_change) = @_;
+ # We need to insert characters as these were removed by old
+ # LogActivityEntry code.
+
+ if ($current_change eq '') {
+ return $new_change;
+ }
+
+ # Buglists and see_also need the comma restored
+ if ($field eq 'dependson' || $field eq 'blocked' || $field eq 'see_also') {
+ if (substr($new_change, 0, 1) eq ',') {
+ return $current_change . $new_change;
+ } else {
+ return $current_change . ', ' . $new_change;
+ }
+ }
+
+ # Assume bug_file_loc contain a single url, don't insert a delimiter
+ if ($field eq 'bug_file_loc') {
+ return $current_change . $new_change;
+ }
+
+ # All other fields get a space
+ if (substr($new_change, 0, 1) eq ' ') {
+ return $current_change . $new_change;
+ } else {
+ return $current_change . ' ' . $new_change;
+ }
+}
+
# Update the bugs_activity table to reflect changes made in bugs.
sub LogActivityEntry {
my ($i, $col, $removed, $added, $whoid, $timestamp, $comment_id) = @_;
@@ -3843,7 +3981,6 @@ sub LogActivityEntry {
my $commaposition = find_wrap_point($removed, MAX_LINE_LENGTH);
$removestr = substr($removed, 0, $commaposition);
$removed = substr($removed, $commaposition);
- $removed =~ s/^[,\s]+//; # remove any comma or space
} else {
$removed = ""; # no more entries
}
@@ -3851,7 +3988,6 @@ sub LogActivityEntry {
my $commaposition = find_wrap_point($added, MAX_LINE_LENGTH);
$addstr = substr($added, 0, $commaposition);
$added = substr($added, $commaposition);
- $added =~ s/^[,\s]+//; # remove any comma or space
} else {
$added = ""; # no more entries
}
@@ -3938,8 +4074,8 @@ sub check_can_change_field {
return 1;
}
- # Allow anyone to change comments.
- if ($field =~ /^longdesc/) {
+ # Allow anyone to change comments, or set flags
+ if ($field =~ /^longdesc/ || $field eq 'flagtypes.name') {
return 1;
}
diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm
index 55eeeab25..37421ce3e 100644
--- a/Bugzilla/BugMail.pm
+++ b/Bugzilla/BugMail.pm
@@ -47,7 +47,8 @@ use Bugzilla::Hook;
use Date::Parse;
use Date::Format;
use Scalar::Util qw(blessed);
-use List::MoreUtils qw(uniq);
+use List::MoreUtils qw(uniq firstidx);
+use Sys::Hostname;
use constant BIT_DIRECT => 1;
use constant BIT_WATCHING => 2;
@@ -107,30 +108,50 @@ sub Send {
my %user_cache = map { $_->id => $_ } (@assignees, @qa_contacts, @ccs);
my @diffs;
+ my @referenced_bugs;
if (!$start) {
@diffs = _get_new_bugmail_fields($bug);
}
if ($params->{dep_only}) {
+ my $fields = Bugzilla->fields({ by_name => 1 });
push(@diffs, { field_name => 'bug_status',
+ field_desc => $fields->{bug_status}->description,
old => $params->{changes}->{bug_status}->[0],
new => $params->{changes}->{bug_status}->[1],
login_name => $changer->login,
blocker => $params->{blocker} },
{ field_name => 'resolution',
+ field_desc => $fields->{resolution}->description,
old => $params->{changes}->{resolution}->[0],
new => $params->{changes}->{resolution}->[1],
login_name => $changer->login,
blocker => $params->{blocker} });
+ push(@referenced_bugs, $params->{blocker}->id);
}
else {
- push(@diffs, _get_diffs($bug, $end, \%user_cache));
+ my ($diffs, $referenced) = _get_diffs($bug, $end, \%user_cache);
+ push(@diffs, @$diffs);
+ push(@referenced_bugs, @$referenced);
}
my $comments = $bug->comments({ after => $start, to => $end });
# Skip empty comments.
@$comments = grep { $_->type || $_->body =~ /\S/ } @$comments;
+ # Add duplicate bug to referenced bug list
+ foreach my $comment (@$comments) {
+ if ($comment->type == CMT_DUPE_OF || $comment->type == CMT_HAS_DUPE) {
+ push(@referenced_bugs, $comment->extra_data);
+ }
+ }
+
+ # Add dependencies to referenced bug list on new bugs
+ if (!$start) {
+ push @referenced_bugs, @{ $bug->dependson };
+ push @referenced_bugs, @{ $bug->blocked };
+ }
+
###########################################################################
# Start of email filtering code
###########################################################################
@@ -193,21 +214,23 @@ sub Send {
{ bug => $bug, recipients => \%recipients,
users => \%user_cache, diffs => \@diffs });
- # Find all those user-watching anyone on the current list, who is not
- # on it already themselves.
- my $involved = join(",", keys %recipients);
+ if (scalar keys %recipients) {
+ # Find all those user-watching anyone on the current list, who is not
+ # on it already themselves.
+ my $involved = join(",", keys %recipients);
- my $userwatchers =
- $dbh->selectall_arrayref("SELECT watcher, watched FROM watch
- WHERE watched IN ($involved)");
+ my $userwatchers =
+ $dbh->selectall_arrayref("SELECT watcher, watched FROM watch
+ WHERE watched IN ($involved)");
- # Mark these people as having the role of the person they are watching
- foreach my $watch (@$userwatchers) {
- while (my ($role, $bits) = each %{$recipients{$watch->[1]}}) {
- $recipients{$watch->[0]}->{$role} |= BIT_WATCHING
- if $bits & BIT_DIRECT;
+ # Mark these people as having the role of the person they are watching
+ foreach my $watch (@$userwatchers) {
+ while (my ($role, $bits) = each %{$recipients{$watch->[1]}}) {
+ $recipients{$watch->[0]}->{$role} |= BIT_WATCHING
+ if $bits & BIT_DIRECT;
+ }
+ push(@{$watching{$watch->[0]}}, $watch->[1]);
}
- push(@{$watching{$watch->[0]}}, $watch->[1]);
}
# Global watcher
@@ -229,6 +252,9 @@ sub Send {
my $date = $params->{dep_only} ? $end : $bug->delta_ts;
$date = format_time($date, '%a, %d %b %Y %T %z', 'UTC');
+ # Remove duplicate references, and convert to bug objects
+ @referenced_bugs = @{ Bugzilla::Bug->new_from_list([uniq @referenced_bugs]) };
+
foreach my $user_id (keys %recipients) {
my %rels_which_want;
my $sent_mail = 0;
@@ -237,6 +263,13 @@ sub Send {
# Deleted users must be excluded.
next unless $user;
+ # If email notifications are disabled for this account, or the bug
+ # is ignored, there is no need to do additional checks.
+ if ($user->email_disabled || $user->is_bug_ignored($id)) {
+ push(@excluded, $user->login);
+ next;
+ }
+
if ($user->can_see_bug($id)) {
# Go through each role the user has and see if they want mail in
# that role.
@@ -253,7 +286,7 @@ sub Send {
}
}
}
-
+
if (scalar(%rels_which_want)) {
# So the user exists, can see the bug, and wants mail in at least
# one role. But do we want to send it to them?
@@ -267,8 +300,33 @@ sub Send {
}
# Make sure the user isn't in the nomail list, and the dep check passed.
- if ($user->email_enabled && $dep_ok) {
- # OK, OK, if we must. Email the user.
+ # BMO: never send emails to bugs or .tld addresses. this check needs to
+ # happen after the bugmail_recipients hook.
+ if ($user->email_enabled && $dep_ok &&
+ ($user->login !~ /bugs$/) &&
+ # sync-1@bugzilla.tld here is a temporary hack, see bug 844724
+ ($user->login eq 'sync-1@bugzilla.tld' || $user->login !~ /\.tld$/))
+
+ {
+ # Don't show summaries for bugs the user can't access, and
+ # provide a hook for extensions such as SecureMail to filter
+ # this list.
+ #
+ # We build an array with the short_desc as a separate item to
+ # allow extensions to modify the summary without touching the
+ # bug object.
+ my $referenced_bugs = [];
+ foreach my $ref (@{ $user->visible_bugs(\@referenced_bugs) }) {
+ push @$referenced_bugs, {
+ bug => $ref,
+ id => $ref->id,
+ short_desc => $ref->short_desc,
+ };
+ }
+ Bugzilla::Hook::process('bugmail_referenced_bugs',
+ { updated_bug => $bug,
+ referenced_bugs => $referenced_bugs });
+
$sent_mail = sendMail(
{ to => $user,
bug => $bug,
@@ -279,6 +337,7 @@ sub Send {
$watching{$user_id} : undef,
diffs => \@diffs,
rels_which_want => \%rels_which_want,
+ referenced_bugs => $referenced_bugs,
});
}
}
@@ -314,6 +373,7 @@ sub sendMail {
my $watchingRef = $params->{watchers};
my @diffs = @{ $params->{diffs} };
my $relRef = $params->{rels_which_want};
+ my $referenced_bugs = $params->{referenced_bugs};
# Only display changes the user is allowed see.
my @display_diffs;
@@ -352,6 +412,17 @@ sub sendMail {
push(@watchingrel, 'None') unless @watchingrel;
push @watchingrel, map { user_id_to_login($_) } @$watchingRef;
+ # BMO: Use field descriptions instead of field names in header
+ my @changedfields = uniq map { $_->{field_desc} } @display_diffs;
+ my @changedfieldnames = uniq map { $_->{field_name} } @display_diffs;
+
+ # Add attachments.created to changedfields if one or more
+ # comments contain information about a new attachment
+ if (grep($_->type == CMT_ATTACHMENT_CREATED, @send_comments)) {
+ push(@changedfields, 'Attachment Created');
+ push(@changedfieldnames, 'attachment.created');
+ }
+
my $vars = {
date => $date,
to_user => $user,
@@ -362,9 +433,11 @@ sub sendMail {
reasonswatchheader => join(" ", @watchingrel),
changer => $changer,
diffs => \@display_diffs,
- changedfields => [uniq map { $_->{field_name} } @display_diffs],
+ changedfields => \@changedfields,
+ changedfieldnames => \@changedfieldnames,
new_comments => \@send_comments,
threadingmarker => build_thread_marker($bug->id, $user->id, !$bug->lastdiffed),
+ referenced_bugs => $referenced_bugs,
};
my $msg = _generate_bugmail($user, $vars);
MessageToMTA($msg);
@@ -395,7 +468,7 @@ sub _generate_bugmail {
|| ThrowTemplateError($template->error());
push @parts, Email::MIME->create(
attributes => {
- content_type => "text/html",
+ content_type => "text/html",
},
body => $msg_html,
);
@@ -403,6 +476,10 @@ sub _generate_bugmail {
# TT trims the trailing newline, and threadingmarker may be ignored.
my $email = new Email::MIME("$msg_header\n");
+
+ # For tracking/diagnostic purposes, add our hostname
+ $email->header_set('X-Generated-By' => hostname());
+
if (scalar(@parts) == 1) {
$email->content_type_set($parts[0]->content_type);
} else {
@@ -426,6 +503,7 @@ sub _get_diffs {
my $diffs = $dbh->selectall_arrayref(
"SELECT fielddefs.name AS field_name,
+ fielddefs.description AS field_desc,
bugs_activity.bug_when, bugs_activity.removed AS old,
bugs_activity.added AS new, bugs_activity.attach_id,
bugs_activity.comment_id, bugs_activity.who
@@ -434,11 +512,12 @@ sub _get_diffs {
ON fielddefs.id = bugs_activity.fieldid
WHERE bugs_activity.bug_id = ?
$when_restriction
- ORDER BY bugs_activity.bug_when", {Slice=>{}}, @args);
+ ORDER BY bugs_activity.bug_when, fielddefs.description", {Slice=>{}}, @args);
+ my $referenced_bugs = [];
foreach my $diff (@$diffs) {
- $user_cache->{$diff->{who}} ||= new Bugzilla::User($diff->{who});
- $diff->{who} = $user_cache->{$diff->{who}};
+ $user_cache->{$diff->{who}} ||= new Bugzilla::User($diff->{who});
+ $diff->{who} = $user_cache->{$diff->{who}};
if ($diff->{attach_id}) {
$diff->{isprivate} = $dbh->selectrow_array(
'SELECT isprivate FROM attachments WHERE attach_id = ?',
@@ -449,9 +528,13 @@ sub _get_diffs {
$diff->{num} = $comment->count;
$diff->{isprivate} = $diff->{new};
}
+ elsif ($diff->{field_name} eq 'dependson' || $diff->{field_name} eq 'blocked') {
+ push @$referenced_bugs, grep { /^\d+$/ } split(/[\s,]+/, $diff->{old});
+ push @$referenced_bugs, grep { /^\d+$/ } split(/[\s,]+/, $diff->{new});
+ }
}
- return @$diffs;
+ return ($diffs, $referenced_bugs);
}
sub _get_new_bugmail_fields {
@@ -459,6 +542,20 @@ sub _get_new_bugmail_fields {
my @fields = @{ Bugzilla->fields({obsolete => 0, in_new_bugmail => 1}) };
my @diffs;
+ # Show fields in the same order as the DEFAULT_FIELDS list, which mirrors
+ # 4.0's behavour and provides sane grouping of similar fields.
+ # Any additional fields are sorted by descrsiption
+ my @prepend;
+ foreach my $name (map { $_->{name} } Bugzilla::Field::DEFAULT_FIELDS) {
+ my $idx = firstidx { $_->name eq $name } @fields;
+ if ($idx != -1) {
+ push(@prepend, $fields[$idx]);
+ splice(@fields, $idx, 1);
+ }
+ }
+ @fields = sort { $a->description cmp $b->description } @fields;
+ @fields = (@prepend, @fields);
+
foreach my $field (@fields) {
my $name = $field->name;
my $value = $bug->$name;
@@ -484,7 +581,9 @@ sub _get_new_bugmail_fields {
# If there isn't anything to show, don't include this header.
next unless $value;
- push(@diffs, {field_name => $name, new => $value});
+ push(@diffs, {field_name => $name,
+ field_desc => $field->description,
+ new => $value});
}
return @diffs;
diff --git a/Bugzilla/BugUrl.pm b/Bugzilla/BugUrl.pm
index 837c0d4fe..784600984 100644
--- a/Bugzilla/BugUrl.pm
+++ b/Bugzilla/BugUrl.pm
@@ -69,6 +69,7 @@ use constant SUB_CLASSES => qw(
Bugzilla::BugUrl::Trac
Bugzilla::BugUrl::MantisBT
Bugzilla::BugUrl::SourceForge
+ Bugzilla::BugUrl::GitHub
);
###############################
diff --git a/Bugzilla/BugUrl/GitHub.pm b/Bugzilla/BugUrl/GitHub.pm
new file mode 100644
index 000000000..63be65bed
--- /dev/null
+++ b/Bugzilla/BugUrl/GitHub.pm
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::BugUrl::GitHub;
+use strict;
+use base qw(Bugzilla::BugUrl);
+
+###############################
+#### Methods ####
+###############################
+
+sub should_handle {
+ my ($class, $uri) = @_;
+
+ # GitHub issue URLs have only one form:
+ # https://github.com/USER_OR_TEAM_OR_ORGANIZATION_NAME/REPOSITORY_NAME/issues/111
+ return ($uri->authority =~ /^github.com$/i
+ and $uri->path =~ m|^/[^/]+/[^/]+/issues/\d+$|) ? 1 : 0;
+}
+
+sub _check_value {
+ my ($class, $uri) = @_;
+
+ $uri = $class->SUPER::_check_value($uri);
+
+ # GitHub HTTP URLs redirect to HTTPS, so just use the HTTPS scheme.
+ $uri->scheme('https');
+
+ return $uri;
+}
+
+1;
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm
index 4dd223a31..2feb0b098 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -73,11 +73,22 @@ sub new {
# Make sure our outgoing cookie list is empty on each invocation
$self->{Bugzilla_cookie_list} = [];
+ # Path-Info is of no use for Bugzilla and interacts badly with IIS.
+ # Moreover, it causes unexpected behaviors, such as totally breaking
+ # the rendering of pages.
+ my $script = basename($0);
+ if ($self->path_info) {
+ my @whitelist;
+ Bugzilla::Hook::process('path_info_whitelist', { whitelist => \@whitelist });
+ if (!grep($_ eq $script, @whitelist)) {
+ print $self->redirect($self->url(-path => 0, -query => 1));
+ }
+ }
+
# Send appropriate charset
$self->charset(Bugzilla->params->{'utf8'} ? 'UTF-8' : '');
# Redirect to urlbase/sslbase if we are not viewing an attachment.
- my $script = basename($0);
if ($self->url_is_attachment_base and $script ne 'attachment.cgi') {
$self->redirect_to_urlbase();
}
diff --git a/Bugzilla/Comment.pm b/Bugzilla/Comment.pm
index ee342fb2d..ae68e3916 100644
--- a/Bugzilla/Comment.pm
+++ b/Bugzilla/Comment.pm
@@ -93,7 +93,7 @@ use constant VALIDATOR_DEPENDENCIES => {
sub update {
my $self = shift;
my $changes = $self->SUPER::update(@_);
- $self->bug->_sync_fulltext();
+ $self->bug->_sync_fulltext( update_comments => 1);
return $changes;
}
@@ -143,7 +143,8 @@ sub is_about_attachment {
sub attachment {
my ($self) = @_;
return undef if not $self->is_about_attachment;
- $self->{attachment} ||= new Bugzilla::Attachment($self->extra_data);
+ $self->{attachment} ||=
+ new Bugzilla::Attachment({ id => $self->extra_data, cache => 1 });
return $self->{attachment};
}
diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm
index dc3cc1b9e..ad5166a0f 100644
--- a/Bugzilla/Component.pm
+++ b/Bugzilla/Component.pm
@@ -371,11 +371,13 @@ sub default_qa_contact {
}
sub flag_types {
- my $self = shift;
+ my ($self, $params) = @_;
+ $params ||= {};
if (!defined $self->{'flag_types'}) {
my $flagtypes = Bugzilla::FlagType::match({ product_id => $self->product_id,
- component_id => $self->id });
+ component_id => $self->id,
+ %$params });
$self->{'flag_types'} = {};
$self->{'flag_types'}->{'bug'} =
diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm
index 990fd8dd2..3e9b793a6 100644
--- a/Bugzilla/Config.pm
+++ b/Bugzilla/Config.pm
@@ -35,7 +35,6 @@ use strict;
use base qw(Exporter);
use Bugzilla::Constants;
use Bugzilla::Hook;
-use Bugzilla::Install::Filesystem qw(fix_file_permissions);
use Data::Dumper;
use File::Temp;
@@ -301,7 +300,10 @@ sub write_params {
rename $tmpname, $param_file
or die "Can't rename $tmpname to $param_file: $!";
- fix_file_permissions($param_file);
+ # It's not common to edit parameters and loading
+ # Bugzilla::Install::Filesystem is slow.
+ require Bugzilla::Install::Filesystem;
+ Bugzilla::Install::Filesystem::fix_file_permissions($param_file);
# And now we have to reset the params cache so that Bugzilla will re-read
# them.
diff --git a/Bugzilla/Config/Advanced.pm b/Bugzilla/Config/Advanced.pm
index 941cefc4f..a5ae3048a 100644
--- a/Bugzilla/Config/Advanced.pm
+++ b/Bugzilla/Config/Advanced.pm
@@ -63,6 +63,18 @@ use constant get_param_list => (
default => 'off',
checker => \&check_multi
},
+
+ {
+ name => 'disable_bug_updates',
+ type => 'b',
+ default => 0
+ },
+
+ {
+ name => 'arecibo_server',
+ type => 't',
+ default => '',
+ },
);
1;
diff --git a/Bugzilla/Config/Auth.pm b/Bugzilla/Config/Auth.pm
index a61cab5a2..d70c1f81e 100644
--- a/Bugzilla/Config/Auth.pm
+++ b/Bugzilla/Config/Auth.pm
@@ -97,6 +97,12 @@ sub get_param_list {
},
{
+ name => 'webservice_email_filter',
+ type => 'b',
+ default => 0
+ },
+
+ {
name => 'emailregexp',
type => 't',
default => q:^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$:,
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 9219db69e..c31565dd8 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -105,7 +105,7 @@ use Memoize;
POS_EVENTS
EVT_OTHER EVT_ADDED_REMOVED EVT_COMMENT EVT_ATTACHMENT EVT_ATTACHMENT_DATA
EVT_PROJ_MANAGEMENT EVT_OPENED_CLOSED EVT_KEYWORD EVT_CC EVT_DEPEND_BLOCK
- EVT_BUG_CREATED
+ EVT_BUG_CREATED EVT_COMPONENT
NEG_EVENTS
EVT_UNCONFIRMED EVT_CHANGED_BY_ME
@@ -182,6 +182,7 @@ use Memoize;
MAX_FREETEXT_LENGTH
MAX_BUG_URL_LENGTH
MAX_POSSIBLE_DUPLICATES
+ MAX_WEBDOT_BUGS
PASSWORD_DIGEST_ALGORITHM
PASSWORD_SALT_LENGTH
@@ -262,7 +263,8 @@ use constant AUTH_NO_SUCH_USER => 5;
use constant AUTH_LOCKOUT => 6;
# The minimum length a password must have.
-use constant USER_PASSWORD_MIN_LENGTH => 6;
+# BMO uses 8 characters.
+use constant USER_PASSWORD_MIN_LENGTH => 8;
use constant LOGIN_OPTIONAL => 0;
use constant LOGIN_NORMAL => 1;
@@ -355,11 +357,13 @@ use constant EVT_KEYWORD => 7;
use constant EVT_CC => 8;
use constant EVT_DEPEND_BLOCK => 9;
use constant EVT_BUG_CREATED => 10;
+use constant EVT_COMPONENT => 11;
use constant POS_EVENTS => EVT_OTHER, EVT_ADDED_REMOVED, EVT_COMMENT,
EVT_ATTACHMENT, EVT_ATTACHMENT_DATA,
EVT_PROJ_MANAGEMENT, EVT_OPENED_CLOSED, EVT_KEYWORD,
- EVT_CC, EVT_DEPEND_BLOCK, EVT_BUG_CREATED;
+ EVT_CC, EVT_DEPEND_BLOCK, EVT_BUG_CREATED,
+ EVT_COMPONENT;
use constant EVT_UNCONFIRMED => 50;
use constant EVT_CHANGED_BY_ME => 51;
@@ -431,8 +435,8 @@ use constant MAX_LOGIN_ATTEMPTS => 5;
use constant LOGIN_LOCKOUT_INTERVAL => 30;
# The maximum number of seconds the Strict-Transport-Security header
-# will remain valid. Default is one week.
-use constant MAX_STS_AGE => 604800;
+# will remain valid. BMO uses one year.
+use constant MAX_STS_AGE => 31536000;
# Protocols which are considered as safe.
use constant SAFE_PROTOCOLS => ('afs', 'cid', 'ftp', 'gopher', 'http', 'https',
@@ -445,15 +449,16 @@ use constant LEGAL_CONTENT_TYPES => ('application', 'audio', 'image', 'message',
use constant contenttypes =>
{
- "html"=> "text/html" ,
- "rdf" => "application/rdf+xml" ,
- "atom"=> "application/atom+xml" ,
- "xml" => "application/xml" ,
- "js" => "application/x-javascript" ,
- "json"=> "application/json" ,
- "csv" => "text/csv" ,
- "png" => "image/png" ,
- "ics" => "text/calendar" ,
+ "html" => "text/html" ,
+ "rdf" => "application/rdf+xml" ,
+ "atom" => "application/atom+xml" ,
+ "xml" => "application/xml" ,
+ "dtd" => "application/xml-dtd" ,
+ "js" => "application/x-javascript" ,
+ "json" => "application/json" ,
+ "csv" => "text/csv" ,
+ "png" => "image/png" ,
+ "ics" => "text/calendar" ,
};
# Usage modes. Default USAGE_MODE_BROWSER. Use with Bugzilla->usage_mode.
@@ -562,6 +567,9 @@ use constant MAX_BUG_URL_LENGTH => 255;
# will return.
use constant MAX_POSSIBLE_DUPLICATES => 25;
+# Maximum number of bugs to display in a dependency graph
+use constant MAX_WEBDOT_BUGS => 2000;
+
# This is the name of the algorithm used to hash passwords before storing
# them in the database. This can be any string that is valid to pass to
# Perl's "Digest" module. Note that if you change this, it won't take
diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm
index 0c841632f..5eb44c403 100644
--- a/Bugzilla/DB.pm
+++ b/Bugzilla/DB.pm
@@ -159,7 +159,7 @@ sub _handle_error {
# Cut down the error string to a reasonable size
$_[0] = substr($_[0], 0, 2000) . ' ... ' . substr($_[0], -2000)
if length($_[0]) > 4000;
- $_[0] = Carp::longmess($_[0]);
+ # BMO: stracktrace disabled: $_[0] = Carp::longmess($_[0]);
return 0; # Now let DBI handle raising the error
}
@@ -405,8 +405,10 @@ sub sql_string_until {
}
sub sql_in {
- my ($self, $column_name, $in_list_ref) = @_;
- return " $column_name IN (" . join(',', @$in_list_ref) . ") ";
+ my ($self, $column_name, $in_list_ref, $negate) = @_;
+ return " $column_name "
+ . ($negate ? "NOT " : "")
+ . "IN (" . join(',', @$in_list_ref) . ") ";
}
sub sql_fulltext_search {
diff --git a/Bugzilla/DB/Oracle.pm b/Bugzilla/DB/Oracle.pm
index 622609f15..644276898 100644
--- a/Bugzilla/DB/Oracle.pm
+++ b/Bugzilla/DB/Oracle.pm
@@ -216,16 +216,16 @@ sub sql_position {
}
sub sql_in {
- my ($self, $column_name, $in_list_ref) = @_;
+ my ($self, $column_name, $in_list_ref, $negate) = @_;
my @in_list = @$in_list_ref;
- return $self->SUPER::sql_in($column_name, $in_list_ref) if $#in_list < 1000;
+ return $self->SUPER::sql_in($column_name, $in_list_ref, $negate) if $#in_list < 1000;
my @in_str;
while (@in_list) {
my $length = $#in_list + 1;
my $splice = $length > 1000 ? 1000 : $length;
my @sub_in_list = splice(@in_list, 0, $splice);
push(@in_str,
- $self->SUPER::sql_in($column_name, \@sub_in_list));
+ $self->SUPER::sql_in($column_name, \@sub_in_list, $negate));
}
return "( " . join(" OR ", @in_str) . " )";
}
diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 1e598c61e..89f0e1ecb 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -342,6 +342,8 @@ use constant ABSTRACT_SCHEMA => {
bugs_activity => {
FIELDS => [
+ id => {TYPE => 'INTSERIAL', NOTNULL => 1,
+ PRIMARYKEY => 1},
bug_id => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'bugs',
COLUMN => 'bug_id',
@@ -358,8 +360,8 @@ use constant ABSTRACT_SCHEMA => {
REFERENCES => {TABLE => 'fielddefs',
COLUMN => 'id'}},
added => {TYPE => 'varchar(255)'},
- removed => {TYPE => 'TINYTEXT'},
- comment_id => {TYPE => 'INT3',
+ removed => {TYPE => 'varchar(255)'},
+ comment_id => {TYPE => 'INT4',
REFERENCES => { TABLE => 'longdescs',
COLUMN => 'comment_id',
DELETE => 'CASCADE'}},
@@ -370,6 +372,7 @@ use constant ABSTRACT_SCHEMA => {
bugs_activity_bug_when_idx => ['bug_when'],
bugs_activity_fieldid_idx => ['fieldid'],
bugs_activity_added_idx => ['added'],
+ bugs_activity_removed_idx => ['removed'],
],
},
@@ -393,7 +396,7 @@ use constant ABSTRACT_SCHEMA => {
longdescs => {
FIELDS => [
- comment_id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1,
+ comment_id => {TYPE => 'INTSERIAL', NOTNULL => 1,
PRIMARYKEY => 1},
bug_id => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'bugs',
@@ -433,7 +436,8 @@ use constant ABSTRACT_SCHEMA => {
DELETE => 'CASCADE'}},
],
INDEXES => [
- dependencies_blocked_idx => ['blocked'],
+ dependencies_blocked_idx => {FIELDS => [qw(blocked dependson)],
+ TYPE => 'UNIQUE'},
dependencies_dependson_idx => ['dependson'],
],
},
@@ -651,8 +655,8 @@ use constant ABSTRACT_SCHEMA => {
DELETE => 'CASCADE'}},
],
INDEXES => [
- flaginclusions_type_id_idx =>
- [qw(type_id product_id component_id)],
+ flaginclusions_type_id_idx => { FIELDS => [qw(type_id product_id component_id)],
+ TYPE => 'UNIQUE' },
],
},
@@ -672,8 +676,8 @@ use constant ABSTRACT_SCHEMA => {
DELETE => 'CASCADE'}},
],
INDEXES => [
- flagexclusions_type_id_idx =>
- [qw(type_id product_id component_id)],
+ flagexclusions_type_id_idx => { FIELDS => [qw(type_id product_id component_id)],
+ TYPE => 'UNIQUE' },
],
},
@@ -915,6 +919,8 @@ use constant ABSTRACT_SCHEMA => {
profiles_activity => {
FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1,
+ PRIMARYKEY => 1},
userid => {TYPE => 'INT3', NOTNULL => 1,
REFERENCES => {TABLE => 'profiles',
COLUMN => 'userid',
@@ -952,6 +958,23 @@ use constant ABSTRACT_SCHEMA => {
],
},
+ email_bug_ignore => {
+ FIELDS => [
+ user_id => {TYPE => 'INT3', NOTNULL => 1,
+ REFERENCES => {TABLE => 'profiles',
+ COLUMN => 'userid',
+ DELETE => 'CASCADE'}},
+ bug_id => {TYPE => 'INT3', NOTNULL => 1,
+ REFERENCES => {TABLE => 'bugs',
+ COLUMN => 'bug_id',
+ DELETE => 'CASCADE'}},
+ ],
+ INDEXES => [
+ email_bug_ignore_user_id_idx => {FIELDS => [qw(user_id bug_id)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
watch => {
FIELDS => [
watcher => {TYPE => 'INT3', NOTNULL => 1,
diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm
index 178f6f90c..e49f466d6 100644
--- a/Bugzilla/Error.pm
+++ b/Bugzilla/Error.pm
@@ -26,8 +26,9 @@ package Bugzilla::Error;
use strict;
use base qw(Exporter);
-@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
+@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError ThrowErrorPage);
+use Bugzilla::Arecibo;
use Bugzilla::Constants;
use Bugzilla::WebService::Constants;
use Bugzilla::Util;
@@ -93,6 +94,7 @@ sub _throw_error {
my $template = Bugzilla->template;
my $message;
+
# There are some tests that throw and catch a lot of errors,
# and calling $template->process over and over for those errors
# is too slow. So instead, we just "die" with a dump of the arguments.
@@ -108,8 +110,22 @@ sub _throw_error {
message => \$message });
if (Bugzilla->error_mode == ERROR_MODE_WEBPAGE) {
+ if (arecibo_should_notify($vars->{error})) {
+ $vars->{maintainers_notified} = 1;
+ $vars->{uid} = arecibo_generate_id();
+ $vars->{processed} = {};
+ } else {
+ $vars->{maintainers_notified} = 0;
+ }
+
print Bugzilla->cgi->header();
- print $message;
+ $template->process($name, $vars)
+ || ThrowTemplateError($template->error());
+
+ if ($vars->{maintainers_notified}) {
+ arecibo_handle_error(
+ $vars->{error}, $vars->{processed}->{error_message}, $vars->{uid});
+ }
}
elsif (Bugzilla->error_mode == ERROR_MODE_TEST) {
die Dumper($vars);
@@ -183,40 +199,85 @@ sub ThrowTemplateError {
die("error: template error: $template_err");
}
+ # mod_perl overrides exit to call die with this string
+ # we never want to display this to the user
+ exit if $template_err =~ /\bModPerl::Util::exit\b/;
+
$vars->{'template_error_msg'} = $template_err;
$vars->{'error'} = "template_error";
+ $vars->{'uid'} = arecibo_generate_id();
+ arecibo_handle_error('error', $template_err, $vars->{'uid'});
+ $vars->{'template_error_msg'} =~ s/ at \S+ line \d+\.\s*$//;
+
my $template = Bugzilla->template;
# Try a template first; but if this one fails too, fall back
# on plain old print statements.
if (!$template->process("global/code-error.html.tmpl", $vars)) {
- my $maintainer = Bugzilla->params->{'maintainer'};
+ my $maintainer = html_quote(Bugzilla->params->{'maintainer'});
my $error = html_quote($vars->{'template_error_msg'});
my $error2 = html_quote($template->error());
+ my $uid = html_quote($vars->{'uid'});
print <<END;
<tt>
<p>
- Bugzilla has suffered an internal error. Please save this page and
- send it to $maintainer with details of what you were doing at the
- time this message appeared.
+ Bugzilla has suffered an internal error:
+ </p>
+ <p>
+ $error
+ </p>
+ <!-- template error, no real need to show this to the user
+ $error2
+ -->
+ <p>
+ The <a href="mailto:$maintainer">Bugzilla maintainers</a> have
+ been notified of this error [#$uid].
</p>
- <script type="text/javascript"> <!--
- document.write("<p>URL: " +
- document.location.href.replace(/&/g,"&amp;")
- .replace(/</g,"&lt;")
- .replace(/>/g,"&gt;") + "</p>");
- // -->
- </script>
- <p>Template->process() failed twice.<br>
- First error: $error<br>
- Second error: $error2</p>
</tt>
END
}
exit;
}
+sub ThrowErrorPage {
+ # BMO customisation for bug 659231
+ my ($template_name, $message) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ $dbh->bz_rollback_transaction() if $dbh->bz_in_transaction();
+
+ if (Bugzilla->error_mode == ERROR_MODE_DIE) {
+ die("error: $message");
+ }
+
+ if (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT
+ || Bugzilla->error_mode == ERROR_MODE_JSON_RPC)
+ {
+ my $code = ERROR_UNKNOWN_TRANSIENT;
+ if (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) {
+ die SOAP::Fault->faultcode($code)->faultstring($message);
+ } else {
+ my $server = Bugzilla->_json_server;
+ $server->raise_error(code => 100000 + $code,
+ message => $message,
+ id => $server->{_bz_request_id},
+ version => $server->version);
+ die if _in_eval();
+ $server->response($server->error_response_header);
+ }
+ } else {
+ my $cgi = Bugzilla->cgi;
+ my $template = Bugzilla->template;
+ my $vars = {};
+ $vars->{message} = $message;
+ print $cgi->header();
+ $template->process($template_name, $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+}
+
1;
__END__
diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm
index 81677c7ea..3d482b3c9 100644
--- a/Bugzilla/Field.pm
+++ b/Bugzilla/Field.pm
@@ -78,6 +78,8 @@ use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Util;
use List::MoreUtils qw(any);
+use Bugzilla::Config qw(SetParam write_params);
+use Bugzilla::Hook;
use Scalar::Util qw(blessed);
@@ -207,9 +209,9 @@ use constant DEFAULT_FIELDS => (
buglist => 1},
{name => 'cc', desc => 'CC', in_new_bugmail => 1},
{name => 'dependson', desc => 'Depends on', in_new_bugmail => 1,
- is_numeric => 1},
+ is_numeric => 1, buglist => 1},
{name => 'blocked', desc => 'Blocks', in_new_bugmail => 1,
- is_numeric => 1},
+ is_numeric => 1, buglist => 1},
{name => 'attachments.description', desc => 'Attachment description'},
{name => 'attachments.filename', desc => 'Attachment filename'},
@@ -918,53 +920,64 @@ sub remove_from_db {
ThrowUserError('customfield_not_obsolete', {'name' => $self->name });
}
- $dbh->bz_start_transaction();
+ # BMO: disable bug updates during field creation
+ # using an eval as try/finally
+ eval {
+ SetParam('disable_bug_updates', 1);
+ write_params();
- # Check to see if bug activity table has records (should be fast with index)
- my $has_activity = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs_activity
- WHERE fieldid = ?", undef, $self->id);
- if ($has_activity) {
- ThrowUserError('customfield_has_activity', {'name' => $name });
- }
+ $dbh->bz_start_transaction();
- # Check to see if bugs table has records (slow)
- my $bugs_query = "";
+ # Check to see if bug activity table has records (should be fast with index)
+ my $has_activity = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs_activity
+ WHERE fieldid = ?", undef, $self->id);
+ if ($has_activity) {
+ ThrowUserError('customfield_has_activity', {'name' => $name });
+ }
- if ($self->type == FIELD_TYPE_MULTI_SELECT) {
- $bugs_query = "SELECT COUNT(*) FROM bug_$name";
- }
- else {
- $bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL";
- if ($self->type != FIELD_TYPE_BUG_ID && $self->type != FIELD_TYPE_DATETIME) {
- $bugs_query .= " AND $name != ''";
+ # Check to see if bugs table has records (slow)
+ my $bugs_query = "";
+
+ if ($self->type == FIELD_TYPE_MULTI_SELECT) {
+ $bugs_query = "SELECT COUNT(*) FROM bug_$name";
}
- # Ignore the default single select value
- if ($self->type == FIELD_TYPE_SINGLE_SELECT) {
- $bugs_query .= " AND $name != '---'";
+ else {
+ $bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL";
+ if ($self->type != FIELD_TYPE_BUG_ID && $self->type != FIELD_TYPE_DATETIME) {
+ $bugs_query .= " AND $name != ''";
+ }
+ # Ignore the default single select value
+ if ($self->type == FIELD_TYPE_SINGLE_SELECT) {
+ $bugs_query .= " AND $name != '---'";
+ }
}
- }
- my $has_bugs = $dbh->selectrow_array($bugs_query);
- if ($has_bugs) {
- ThrowUserError('customfield_has_contents', {'name' => $name });
- }
+ my $has_bugs = $dbh->selectrow_array($bugs_query);
+ if ($has_bugs) {
+ ThrowUserError('customfield_has_contents', {'name' => $name });
+ }
- # Once we reach here, we should be OK to delete.
- $dbh->do('DELETE FROM fielddefs WHERE id = ?', undef, $self->id);
+ # Once we reach here, we should be OK to delete.
+ $dbh->do('DELETE FROM fielddefs WHERE id = ?', undef, $self->id);
- my $type = $self->type;
+ my $type = $self->type;
- # the values for multi-select are stored in a seperate table
- if ($type != FIELD_TYPE_MULTI_SELECT) {
- $dbh->bz_drop_column('bugs', $name);
- }
+ # the values for multi-select are stored in a seperate table
+ if ($type != FIELD_TYPE_MULTI_SELECT) {
+ $dbh->bz_drop_column('bugs', $name);
+ }
- if ($self->is_select) {
- # Delete the table that holds the legal values for this field.
- $dbh->bz_drop_field_tables($self);
- }
+ if ($self->is_select) {
+ # Delete the table that holds the legal values for this field.
+ $dbh->bz_drop_field_tables($self);
+ }
- $dbh->bz_commit_transaction()
+ $dbh->bz_commit_transaction();
+ };
+ my $error = "$@";
+ SetParam('disable_bug_updates', 0);
+ write_params();
+ die $error if $error;
}
=pod
@@ -1012,48 +1025,67 @@ sub create {
my ($params) = @_;
my $dbh = Bugzilla->dbh;
- # This makes sure the "sortkey" validator runs, even if
- # the parameter isn't sent to create().
- $params->{sortkey} = undef if !exists $params->{sortkey};
- $params->{type} ||= 0;
- # We mark the custom field as obsolete till it has been fully created,
- # to avoid race conditions when viewing bugs at the same time.
- my $is_obsolete = $params->{obsolete};
- $params->{obsolete} = 1 if $params->{custom};
-
- $dbh->bz_start_transaction();
- $class->check_required_create_fields(@_);
- my $field_values = $class->run_create_validators($params);
- my $visibility_values = delete $field_values->{visibility_values};
- my $field = $class->insert_create_data($field_values);
-
- $field->set_visibility_values($visibility_values);
- $field->_update_visibility_values();
+ # BMO: disable bug updates during field creation
+ # using an eval as try/finally
+ my $field;
+ eval {
+ if ($params->{'custom'}) {
+ SetParam('disable_bug_updates', 1);
+ write_params();
+ }
- $dbh->bz_commit_transaction();
+ # This makes sure the "sortkey" validator runs, even if
+ # the parameter isn't sent to create().
+ $params->{sortkey} = undef if !exists $params->{sortkey};
+ $params->{type} ||= 0;
+ # We mark the custom field as obsolete till it has been fully created,
+ # to avoid race conditions when viewing bugs at the same time.
+ my $is_obsolete = $params->{obsolete};
+ $params->{obsolete} = 1 if $params->{custom};
+
+ $dbh->bz_start_transaction();
+ $class->check_required_create_fields(@_);
+ my $field_values = $class->run_create_validators($params);
+ my $visibility_values = delete $field_values->{visibility_values};
+ $field = $class->insert_create_data($field_values);
+
+ $field->set_visibility_values($visibility_values);
+ $field->_update_visibility_values();
+
+ $dbh->bz_commit_transaction();
+
+ if ($field->custom) {
+ my $name = $field->name;
+ my $type = $field->type;
+ if (SQL_DEFINITIONS->{$type}) {
+ # Create the database column that stores the data for this field.
+ $dbh->bz_add_column('bugs', $name, SQL_DEFINITIONS->{$type});
+ }
- if ($field->custom) {
- my $name = $field->name;
- my $type = $field->type;
- if (SQL_DEFINITIONS->{$type}) {
- # Create the database column that stores the data for this field.
- $dbh->bz_add_column('bugs', $name, SQL_DEFINITIONS->{$type});
- }
+ if ($field->is_select) {
+ # Create the table that holds the legal values for this field.
+ $dbh->bz_add_field_tables($field);
+ }
- if ($field->is_select) {
- # Create the table that holds the legal values for this field.
- $dbh->bz_add_field_tables($field);
- }
+ if ($type == FIELD_TYPE_SINGLE_SELECT) {
+ # Insert a default value of "---" into the legal values table.
+ $dbh->do("INSERT INTO $name (value) VALUES ('---')");
+ }
- if ($type == FIELD_TYPE_SINGLE_SELECT) {
- # Insert a default value of "---" into the legal values table.
- $dbh->do("INSERT INTO $name (value) VALUES ('---')");
+ # Restore the original obsolete state of the custom field.
+ $dbh->do('UPDATE fielddefs SET obsolete = 0 WHERE id = ?', undef, $field->id)
+ unless $is_obsolete;
}
+ };
- # Restore the original obsolete state of the custom field.
- $dbh->do('UPDATE fielddefs SET obsolete = 0 WHERE id = ?', undef, $field->id)
- unless $is_obsolete;
+ my $error = "$@";
+ if ($params->{'custom'}) {
+ SetParam('disable_bug_updates', 0);
+ write_params();
}
+ die $error if $error;
+
+ Bugzilla::Hook::process("field_end_of_create", { field => $field });
return $field;
}
diff --git a/Bugzilla/Flag.pm b/Bugzilla/Flag.pm
index a727532a6..d3e9b1d37 100644
--- a/Bugzilla/Flag.pm
+++ b/Bugzilla/Flag.pm
@@ -81,15 +81,21 @@ use constant AUDIT_REMOVES => 0;
use constant SKIP_REQUESTEE_ON_ERROR => 1;
-use constant DB_COLUMNS => qw(
- id
- type_id
- bug_id
- attach_id
- requestee_id
- setter_id
- status
-);
+sub DB_COLUMNS {
+ my $dbh = Bugzilla->dbh;
+ return qw(
+ id
+ type_id
+ bug_id
+ attach_id
+ requestee_id
+ setter_id
+ status),
+ $dbh->sql_date_format('creation_date', '%Y.%m.%d %H:%i:%s') .
+ ' AS creation_date',
+ $dbh->sql_date_format('modification_date', '%Y.%m.%d %H:%i:%s') .
+ ' AS modification_date';
+}
use constant UPDATE_COLUMNS => qw(
requestee_id
@@ -134,6 +140,14 @@ Returns the ID of the attachment this flag belongs to, if any.
Returns the status '+', '-', '?' of the flag.
+=item C<creation_date>
+
+Returns the timestamp when the flag was created.
+
+=item C<modification_date>
+
+Returns the timestamp when the flag was last modified.
+
=back
=cut
@@ -146,6 +160,8 @@ sub attach_id { return $_[0]->{'attach_id'}; }
sub status { return $_[0]->{'status'}; }
sub setter_id { return $_[0]->{'setter_id'}; }
sub requestee_id { return $_[0]->{'requestee_id'}; }
+sub creation_date { return $_[0]->{'creation_date'}; }
+sub modification_date { return $_[0]->{'modification_date'}; }
###############################
#### Methods ####
@@ -213,7 +229,7 @@ sub bug {
my $self = shift;
require Bugzilla::Bug;
- $self->{'bug'} ||= new Bugzilla::Bug($self->bug_id);
+ $self->{'bug'} ||= new Bugzilla::Bug({ id => $self->bug_id, cache => 1 });
return $self->{'bug'};
}
@@ -284,7 +300,7 @@ sub count {
sub set_flag {
my ($class, $obj, $params) = @_;
- my ($bug, $attachment);
+ my ($bug, $attachment, $obj_flag, $requestee_changed);
if (blessed($obj) && $obj->isa('Bugzilla::Attachment')) {
$attachment = $obj;
$bug = $attachment->bug;
@@ -296,6 +312,12 @@ sub set_flag {
ThrowCodeError('flag_unexpected_object', { 'caller' => ref $obj });
}
+ # Make sure the user can change flags
+ my $privs;
+ $bug->check_can_change_field('flagtypes.name', 0, 1, \$privs)
+ || ThrowUserError('illegal_change',
+ { field => 'flagtypes.name', privs => $privs });
+
# Update (or delete) an existing flag.
if ($params->{id}) {
my $flag = $class->check({ id => $params->{id} });
@@ -322,13 +344,14 @@ sub set_flag {
($obj_flagtype) = grep { $_->id == $flag->type_id } @{$obj->flag_types};
push(@{$obj_flagtype->{flags}}, $flag);
}
- my ($obj_flag) = grep { $_->id == $flag->id } @{$obj_flagtype->{flags}};
+ ($obj_flag) = grep { $_->id == $flag->id } @{$obj_flagtype->{flags}};
# If the flag has the correct type but cannot be found above, this means
# the flag is going to be removed (e.g. because this is a pending request
# and the attachment is being marked as obsolete).
return unless $obj_flag;
- $class->_validate($obj_flag, $obj_flagtype, $params, $bug, $attachment);
+ ($obj_flag, $requestee_changed) =
+ $class->_validate($obj_flag, $obj_flagtype, $params, $bug, $attachment);
}
# Create a new flag.
elsif ($params->{type_id}) {
@@ -360,12 +383,21 @@ sub set_flag {
}
}
- $class->_validate(undef, $obj_flagtype, $params, $bug, $attachment);
+ ($obj_flag, $requestee_changed) =
+ $class->_validate(undef, $obj_flagtype, $params, $bug, $attachment);
}
else {
ThrowCodeError('param_required', { function => $class . '->set_flag',
param => 'id/type_id' });
}
+
+ if ($obj_flag
+ && $requestee_changed
+ && $obj_flag->requestee_id
+ && $obj_flag->requestee->setting('requestee_cc') eq 'on')
+ {
+ $bug->add_cc($obj_flag->requestee);
+ }
}
sub _validate {
@@ -385,23 +417,25 @@ sub _validate {
$obj_flag->_set_status($params->{status});
$obj_flag->_set_requestee($params->{requestee}, $attachment, $params->{skip_roe});
+ # The requestee ID can be undefined.
+ my $requestee_changed = ($obj_flag->requestee_id || 0) != ($old_requestee_id || 0);
+
# The setter field MUST NOT be updated if neither the status
# nor the requestee fields changed.
- if (($obj_flag->status ne $old_status)
- # The requestee ID can be undefined.
- || (($obj_flag->requestee_id || 0) != ($old_requestee_id || 0)))
- {
+ if (($obj_flag->status ne $old_status) || $requestee_changed) {
$obj_flag->_set_setter($params->{setter});
}
# If the flag is deleted, remove it from the list.
if ($obj_flag->status eq 'X') {
@{$flag_type->{flags}} = grep { $_->id != $obj_flag->id } @{$flag_type->{flags}};
+ return;
}
# Add the newly created flag to the list.
elsif (!$obj_flag->id) {
push(@{$flag_type->{flags}}, $obj_flag);
}
+ return wantarray ? ($obj_flag, $requestee_changed) : $obj_flag;
}
=pod
@@ -418,10 +452,14 @@ Creates a flag record in the database.
sub create {
my ($class, $flag, $timestamp) = @_;
- $timestamp ||= Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ $timestamp ||= Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
my $params = {};
my @columns = grep { $_ ne 'id' } $class->_get_db_columns;
+
+ # Some columns use date formatting so use alias instead
+ @columns = map { /\s+AS\s+(.*)$/ ? $1 : $_ } @columns;
+
$params->{$_} = $flag->{$_} foreach @columns;
$params->{creation_date} = $params->{modification_date} = $timestamp;
@@ -440,6 +478,7 @@ sub update {
if (scalar(keys %$changes)) {
$dbh->do('UPDATE flags SET modification_date = ? WHERE id = ?',
undef, ($timestamp, $self->id));
+ $self->{'modification_date'} = format_time($timestamp, '%Y.%m.%d %T');
}
return $changes;
}
@@ -647,9 +686,15 @@ sub _check_requestee {
# is specifically requestable. For existing flags, if the requestee
# was set before the flag became specifically unrequestable, the
# user can either remove him or leave him alone.
- ThrowCodeError('flag_requestee_disabled', { type => $self->type })
+ ThrowCodeError('flag_type_requestee_disabled', { type => $self->type })
if !$self->type->is_requesteeble;
+ # BMO customisation:
+ # You can't ask a disabled account, as they don't have the ability to
+ # set the flag.
+ ThrowUserError('flag_requestee_disabled', { requestee => $requestee })
+ if !$requestee->is_enabled;
+
# Make sure the requestee can see the bug.
# Note that can_see_bug() will query the DB, so if the bug
# is being added/removed from some groups and these changes
@@ -976,6 +1021,9 @@ sub notify {
}
foreach my $to (keys %recipients) {
+ # Skip sending if user is ignoring the bug.
+ next if ($recipients{$to} && $recipients{$to}->is_bug_ignored($bug->id));
+
# Add threadingmarker to allow flag notification emails to be the
# threaded similar to normal bug change emails.
my $thread_user_id = $recipients{$to} ? $recipients{$to}->id : 0;
diff --git a/Bugzilla/FlagType.pm b/Bugzilla/FlagType.pm
index 811530c42..f2afb6f95 100644
--- a/Bugzilla/FlagType.pm
+++ b/Bugzilla/FlagType.pm
@@ -52,6 +52,7 @@ use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Util;
use Bugzilla::Group;
+use Bugzilla::Hook;
use base qw(Bugzilla::Object);
@@ -133,6 +134,8 @@ sub create {
exclusions => $exclusions });
$flagtype->update();
+ Bugzilla::Hook::process('flagtype_end_of_create', { type => $flagtype });
+
$dbh->bz_commit_transaction();
return $flagtype;
}
@@ -201,6 +204,9 @@ sub update {
undef, $self->id);
}
+ Bugzilla::Hook::process('flagtype_end_of_update',
+ { type => $self, changed => $changes });
+
$dbh->bz_commit_transaction();
return $changes;
}
@@ -601,7 +607,7 @@ sub match {
$tables = join(' ', @$tables);
$criteria = join(' AND ', @criteria);
- my $flagtype_ids = $dbh->selectcol_arrayref("SELECT id FROM $tables WHERE $criteria");
+ my $flagtype_ids = $dbh->selectcol_arrayref("SELECT flagtypes.id FROM $tables WHERE $criteria");
return Bugzilla::FlagType->new_from_list($flagtype_ids);
}
@@ -679,6 +685,11 @@ sub sqlify_criteria {
my $is_active = $criteria->{is_active} ? "1" : "0";
push(@criteria, "flagtypes.is_active = $is_active");
}
+ if (exists($criteria->{active_or_has_flags}) && $criteria->{active_or_has_flags} =~ /^\d+$/) {
+ push(@$tables, "LEFT JOIN flags AS f ON flagtypes.id = f.type_id " .
+ "AND f.bug_id = " . $criteria->{active_or_has_flags});
+ push(@criteria, "(flagtypes.is_active = 1 OR f.id IS NOT NULL)");
+ }
if ($criteria->{product_id}) {
my $product_id = $criteria->{product_id};
detaint_natural($product_id)
diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm
index 382407748..109f06d7f 100644
--- a/Bugzilla/Group.pm
+++ b/Bugzilla/Group.pm
@@ -119,9 +119,10 @@ sub _get_members {
}
sub flag_types {
- my $self = shift;
+ my ($self, $params) = @_;
+ $params ||= {};
require Bugzilla::FlagType;
- $self->{flag_types} ||= Bugzilla::FlagType::match({ group => $self->id });
+ $self->{flag_types} ||= Bugzilla::FlagType::match({ group => $self->id, %$params });
return $self->{flag_types};
}
diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm
index c658989a0..a18b11f77 100644
--- a/Bugzilla/Hook.pm
+++ b/Bugzilla/Hook.pm
@@ -434,6 +434,39 @@ to the user.
=back
+=head2 bug_start_of_update
+
+This happens near the beginning of L<Bugzilla::Bug/update>, after L<Bugzilla::Object/update>
+is called, but before all other special changes are made to the database. Once use case is
+this allows for adding your own entries to the C<changes> hash which gets added to the
+bugs_activity table later keeping you from having to do it yourself. Also this is also helpful
+if your extension needs to add CC members, flags, keywords, groups, etc. This generally
+occurs inside a database transaction.
+
+Params:
+
+=over
+
+=item C<bug>
+
+The changed bug object, with all fields set to their updated values.
+
+=item C<old_bug>
+
+A bug object pulled from the database before the fields were set to
+their updated values (so it has the old values available for each field).
+
+=item C<timestamp>
+
+The timestamp used for all updates in this transaction, as a SQL date
+string.
+
+=item C<changes>
+
+The hash of changed fields. C<< $changes->{field} = [old, new] >>
+
+=back
+
=head2 buglist_columns
This happens in L<Bugzilla::Search/COLUMNS>, which determines legal bug
@@ -1289,6 +1322,22 @@ your template.
=back
+=head2 path_info_whitelist
+
+By default, Bugzilla removes the Path-Info information from URLs before
+passing data to CGI scripts. If this information is needed for your
+customizations, you can enumerate the pages you want to whitelist here.
+
+Params:
+
+=over
+
+=item C<whitelist>
+
+An array of script names that will not have their Path-Info automatically
+removed.
+
+=back
=head2 post_bug_after_creation
diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm
index ce8fe6bad..6019c9d18 100644
--- a/Bugzilla/Install.pm
+++ b/Bugzilla/Install.pm
@@ -93,6 +93,10 @@ sub SETTINGS {
# 2011-06-21 glob@mozilla.com -- Bug 589128
email_format => { options => ['html', 'text_only'],
default => 'html' },
+ # 2011-06-16 glob@mozilla.com -- Bug 663747
+ bugmail_new_prefix => { options => ['on', 'off'], default => 'on' },
+ # 2011-10-11 glob@mozilla.com -- Bug 301656
+ requestee_cc => { options => ['on', 'off'], default => 'on' },
}
};
diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm
index 6b9dd65cd..104caac3b 100644
--- a/Bugzilla/Install/DB.pm
+++ b/Bugzilla/Install/DB.pm
@@ -398,7 +398,7 @@ sub update_table_definitions {
"WHERE initialqacontact = 0");
_migrate_email_prefs_to_new_table();
- _initialize_dependency_tree_changes_email_pref();
+ _initialize_new_email_prefs();
_change_all_mysql_booleans_to_tinyint();
# make classification_id field type be consistent with DB:Schema
@@ -455,7 +455,7 @@ sub update_table_definitions {
# 2005-12-07 altlst@sonic.net -- Bug 225221
$dbh->bz_add_column('longdescs', 'comment_id',
- {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+ {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
_stop_storing_inactive_flags();
_change_short_desc_from_mediumtext_to_varchar();
@@ -607,7 +607,7 @@ sub update_table_definitions {
_fix_series_creator_fk();
# 2009-11-14 dkl@redhat.com - Bug 310450
- $dbh->bz_add_column('bugs_activity', 'comment_id', {TYPE => 'INT3'});
+ $dbh->bz_add_column('bugs_activity', 'comment_id', {TYPE => 'INT4'});
# 2010-04-07 LpSolit@gmail.com - Bug 69621
$dbh->bz_drop_column('bugs', 'keywords');
@@ -669,6 +669,33 @@ sub update_table_definitions {
$dbh->bz_add_index('profile_search', 'profile_search_user_id_idx', [qw(user_id)]);
}
+ # 2012-06-06 dkl@mozilla.com - Bug 762288
+ $dbh->bz_alter_column('bugs_activity', 'removed',
+ { TYPE => 'varchar(255)' });
+ $dbh->bz_add_index('bugs_activity', 'bugs_activity_removed_idx', ['removed']);
+
+ # 2012-06-13 dkl@mozilla.com - Bug 764457
+ $dbh->bz_add_column('bugs_activity', 'id',
+ {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+
+ # 2012-06-13 dkl@mozilla.com - Bug 764466
+ $dbh->bz_add_column('profiles_activity', 'id',
+ {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+
+ # 2012-07-24 dkl@mozilla.com - Bug 776972
+ $dbh->bz_alter_column('bugs_activity', 'id',
+ {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+
+
+ # 2012-07-24 dkl@mozilla.com - Bug 776982
+ _fix_longdescs_primary_key();
+
+ # 2012-08-02 dkl@mozilla.com - Bug 756953
+ _fix_dependencies_dupes();
+
+ # 2013-02-04 dkl@mozilla.com - Bug 824346
+ _fix_flagclusions_indexes();
+
################################################################
# New --TABLE-- changes should go *** A B O V E *** this point #
################################################################
@@ -2396,13 +2423,16 @@ sub _migrate_email_prefs_to_new_table {
}
}
-sub _initialize_dependency_tree_changes_email_pref {
+sub _initialize_new_email_prefs {
my $dbh = Bugzilla->dbh;
# Check for any "new" email settings that wouldn't have been ported over
# during the block above. Since these settings would have otherwise
# fallen under EVT_OTHER, we'll just clone those settings. That way if
# folks have already disabled all of that mail, there won't be any change.
- my %events = ("Dependency Tree Changes" => EVT_DEPEND_BLOCK);
+ my %events = (
+ "Dependency Tree Changes" => EVT_DEPEND_BLOCK,
+ "Product/Component Changes" => EVT_COMPONENT,
+ );
foreach my $desc (keys %events) {
my $event = $events{$desc};
@@ -3220,6 +3250,11 @@ sub _populate_bugs_fulltext {
print "Populating bugs_fulltext with $num_bugs entries...";
print " (this can take a long time.)\n";
}
+
+ # As recommended by Monty Widenius for GNOME's upgrade.
+ # mkanat and justdave concur it'll be helpful for bmo, too.
+ $dbh->do('SET SESSION myisam_sort_buffer_size = 3221225472');
+
my $newline = $dbh->quote("\n");
$dbh->do(
qq{$command INTO bugs_fulltext (bug_id, short_desc, comments,
@@ -3687,6 +3722,70 @@ sub _fix_notnull_defaults {
}
}
+sub _fix_longdescs_primary_key {
+ my $dbh = Bugzilla->dbh;
+ if ($dbh->bz_column_info('longdescs', 'comment_id')->{TYPE} ne 'INTSERIAL') {
+ $dbh->bz_drop_related_fks('longdescs', 'comment_id');
+ $dbh->bz_alter_column('bugs_activity', 'comment_id', {TYPE => 'INT4'});
+ $dbh->bz_alter_column('longdescs', 'comment_id',
+ {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+ }
+}
+
+sub _fix_dependencies_dupes {
+ my $dbh = Bugzilla->dbh;
+ my $blocked_idx = $dbh->bz_index_info('dependencies', 'dependencies_blocked_idx');
+ if ($blocked_idx && scalar @{$blocked_idx->{'FIELDS'}} < 2) {
+ # Remove duplicated entries
+ my $dupes = $dbh->selectall_arrayref("
+ SELECT blocked, dependson, COUNT(*) AS count
+ FROM dependencies " .
+ $dbh->sql_group_by('blocked, dependson') . "
+ HAVING COUNT(*) > 1",
+ { Slice => {} });
+ print "Removing duplicated entries from the 'dependencies' table...\n" if @$dupes;
+ foreach my $dupe (@$dupes) {
+ $dbh->do("DELETE FROM dependencies
+ WHERE blocked = ? AND dependson = ?",
+ undef, $dupe->{blocked}, $dupe->{dependson});
+ $dbh->do("INSERT INTO dependencies (blocked, dependson) VALUES (?, ?)",
+ undef, $dupe->{blocked}, $dupe->{dependson});
+ }
+ $dbh->bz_drop_index('dependencies', 'dependencies_blocked_idx');
+ $dbh->bz_add_index('dependencies', 'dependencies_blocked_idx',
+ { FIELDS => [qw(blocked dependson)], TYPE => 'UNIQUE' });
+ }
+}
+
+sub _fix_flagclusions_indexes {
+ my $dbh = Bugzilla->dbh;
+ foreach my $table ('flaginclusions', 'flagexclusions') {
+ my $index = $table . '_type_id_idx';
+ my $idx_info = $dbh->bz_index_info($table, $index);
+ if ($idx_info && $idx_info->{'TYPE'} ne 'UNIQUE') {
+ # Remove duplicated entries
+ my $dupes = $dbh->selectall_arrayref("
+ SELECT type_id, product_id, component_id, COUNT(*) AS count
+ FROM $table " .
+ $dbh->sql_group_by('type_id, product_id, component_id') . "
+ HAVING COUNT(*) > 1",
+ { Slice => {} });
+ print "Removing duplicated entries from the '$table' table...\n" if @$dupes;
+ foreach my $dupe (@$dupes) {
+ $dbh->do("DELETE FROM $table
+ WHERE type_id = ? AND product_id = ? AND component_id = ?",
+ undef, $dupe->{type_id}, $dupe->{product_id}, $dupe->{component_id});
+ $dbh->do("INSERT INTO $table (type_id, product_id, component_id) VALUES (?, ?, ?)",
+ undef, $dupe->{type_id}, $dupe->{product_id}, $dupe->{component_id});
+ }
+ $dbh->bz_drop_index($table, $index);
+ $dbh->bz_add_index($table, $index,
+ { FIELDS => [qw(type_id product_id component_id)],
+ TYPE => 'UNIQUE' });
+ }
+ }
+}
+
1;
__END__
diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm
index c5215ecfa..86978163b 100644
--- a/Bugzilla/Install/Filesystem.pm
+++ b/Bugzilla/Install/Filesystem.pm
@@ -159,6 +159,7 @@ sub FILESYSTEM {
'runtests.pl' => { perms => OWNER_EXECUTE },
'jobqueue.pl' => { perms => OWNER_EXECUTE },
'migrate.pl' => { perms => OWNER_EXECUTE },
+ 'arecibo.pl' => { perms => OWNER_EXECUTE },
'install-module.pl' => { perms => OWNER_EXECUTE },
'Bugzilla.pm' => { perms => CGI_READ },
@@ -170,6 +171,7 @@ sub FILESYSTEM {
'contrib/README' => { perms => OWNER_WRITE },
'contrib/*/README' => { perms => OWNER_WRITE },
+ 'contrib/sendunsentbugmail.pl' => { perms => WS_EXECUTE },
'docs/bugzilla.ent' => { perms => OWNER_WRITE },
'docs/makedocs.pl' => { perms => OWNER_EXECUTE },
'docs/style.css' => { perms => WS_SERVE },
@@ -179,13 +181,16 @@ sub FILESYSTEM {
"$datadir/old-params.txt" => { perms => OWNER_WRITE },
"$extensionsdir/create.pl" => { perms => OWNER_EXECUTE },
"$extensionsdir/*/*.pl" => { perms => WS_EXECUTE },
+ "$extensionsdir/*/bin/*" => { perms => WS_EXECUTE },
);
# Directories that we want to set the perms on, but not
# recurse through. These are directories we didn't create
# in checkesetup.pl.
+ #
+ # Purpose of BMO change: unknown.
my %non_recurse_dirs = (
- '.' => DIR_WS_SERVE,
+ '.' => 0755,
docs => DIR_WS_SERVE,
);
@@ -243,10 +248,13 @@ sub FILESYSTEM {
dirs => DIR_WS_SERVE },
"$extensionsdir/*/web" => { files => WS_SERVE,
dirs => DIR_WS_SERVE },
-
+
+ # Purpose: allow webserver to read .bzr so we execute bzr commands
+ # in backticks and look at the result over the web. Used to show
+ # bzr history.
+ '.bzr' => { files => WS_SERVE,
+ dirs => DIR_WS_SERVE },
# Directories only for the owner, not for the webserver.
- '.bzr' => { files => OWNER_WRITE,
- dirs => DIR_OWNER_WRITE },
t => { files => OWNER_WRITE,
dirs => DIR_OWNER_WRITE },
xt => { files => OWNER_WRITE,
diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm
index bd8942507..5f6c8bceb 100644
--- a/Bugzilla/Install/Util.pm
+++ b/Bugzilla/Install/Util.pm
@@ -382,7 +382,10 @@ sub include_languages {
# Basically, the way this works is that we have a list of languages
# that we *want*, and a list of languages that Bugzilla actually
- # supports.
+ # supports. If there is only one language installed, we take it.
+ my $supported = supported_languages();
+ return @$supported if @$supported == 1;
+
my $wanted;
if ($params->{language}) {
# We can pass several languages at once as an arrayref
@@ -393,7 +396,6 @@ sub include_languages {
else {
$wanted = _wanted_languages();
}
- my $supported = supported_languages();
my $actual = _wanted_to_actual_languages($wanted, $supported);
return @$actual;
}
diff --git a/Bugzilla/JobQueue.pm b/Bugzilla/JobQueue.pm
index 7ea678345..053928dd0 100644
--- a/Bugzilla/JobQueue.pm
+++ b/Bugzilla/JobQueue.pm
@@ -27,7 +27,9 @@ use strict;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Install::Util qw(install_string);
+use File::Slurp;
use base qw(TheSchwartz);
+use fields qw(_worker_pidfile);
# This maps job names for Bugzilla::JobQueue to the appropriate modules.
# If you add new types of jobs, you should add a mapping here.
@@ -99,6 +101,64 @@ sub insert {
return $retval;
}
+# To avoid memory leaks/fragmentation which tends to happen for long running
+# perl processes; check for jobs, and spawn a new process to empty the queue.
+sub subprocess_worker {
+ my $self = shift;
+
+ my $command = "$0 -p '" . $self->{_worker_pidfile} . "' onepass";
+
+ while (1) {
+ my $time = (time);
+ my @jobs = $self->list_jobs({
+ funcname => $self->{all_abilities},
+ run_after => $time,
+ grabbed_until => $time,
+ limit => 1,
+ });
+ if (@jobs) {
+ $self->debug("Spawning queue worker process");
+ # Run the worker as a daemon
+ system $command;
+ # And poll the PID to detect when the working has finished.
+ # We do this instead of system() to allow for the INT signal to
+ # interrup us and trigger kill_worker().
+ my $pid = read_file($self->{_worker_pidfile}, err_mode => 'quiet');
+ if ($pid) {
+ sleep(3) while(kill(0, $pid));
+ }
+ $self->debug("Queue worker process completed");
+ } else {
+ $self->debug("No jobs found");
+ }
+ sleep(5);
+ }
+}
+
+sub kill_worker {
+ my $self = Bugzilla->job_queue();
+ if ($self->{_worker_pidfile} && -e $self->{_worker_pidfile}) {
+ my $worker_pid = read_file($self->{_worker_pidfile});
+ if ($worker_pid && kill(0, $worker_pid)) {
+ $self->debug("Stopping worker process");
+ system "$0 -f -p '" . $self->{_worker_pidfile} . "' stop";
+ }
+ }
+}
+
+sub set_pidfile {
+ my ($self, $pidfile) = @_;
+ $pidfile =~ s/^(.+)(\..+)$/$1.worker$2/;
+ $self->{_worker_pidfile} = $pidfile;
+}
+
+# Clear the request cache at the start of each run.
+sub work_once {
+ my $self = shift;
+ Bugzilla->clear_request_cache();
+ return $self->SUPER::work_once(@_);
+}
+
1;
__END__
diff --git a/Bugzilla/JobQueue/Runner.pm b/Bugzilla/JobQueue/Runner.pm
index 26755e78f..d45c36647 100644
--- a/Bugzilla/JobQueue/Runner.pm
+++ b/Bugzilla/JobQueue/Runner.pm
@@ -51,6 +51,7 @@ our $initscript = "bugzilla-queue";
sub gd_preconfig {
my $self = shift;
+ $self->{_run_command} = 'subprocess_worker';
my $pidfile = $self->{gd_args}{pidfile};
if (!$pidfile) {
$pidfile = bz_locations()->{datadir} . '/' . $self->{gd_progname}
@@ -196,21 +197,26 @@ sub gd_setup_signals {
$SIG{TERM} = sub { $self->gd_quit_event(); }
}
-sub gd_other_cmd {
- my ($self) = shift;
- if ($ARGV[0] eq "once") {
- $self->_do_work("work_once");
+sub gd_quit_event {
+ Bugzilla->job_queue->kill_worker();
+ exit(1);
+}
- exit(0);
+sub gd_other_cmd {
+ my ($self, $do, $locked) = @_;
+ if ($do eq "once") {
+ $self->{_run_command} = 'work_once';
+ } elsif ($do eq "onepass") {
+ $self->{_run_command} = 'work_until_done';
+ } else {
+ $self->SUPER::gd_other_cmd($do, $locked);
}
-
- $self->SUPER::gd_other_cmd();
}
sub gd_run {
my $self = shift;
-
- $self->_do_work("work");
+ $SIG{__DIE__} = \&Carp::confess if $self->{debug};
+ $self->_do_work($self->{_run_command});
}
sub _do_work {
@@ -218,6 +224,7 @@ sub _do_work {
my $jq = Bugzilla->job_queue();
$jq->set_verbose($self->{debug});
+ $jq->set_pidfile($self->{gd_pidfile});
foreach my $module (values %{ Bugzilla::JobQueue->job_map() }) {
eval "use $module";
$jq->can_do($module);
diff --git a/Bugzilla/Mailer.pm b/Bugzilla/Mailer.pm
index 1c4fb6188..381422821 100644
--- a/Bugzilla/Mailer.pm
+++ b/Bugzilla/Mailer.pm
@@ -55,6 +55,7 @@ BEGIN {
$Return::Value::NO_CLUCK = 1;
}
use Email::Send;
+use Sys::Hostname;
sub MessageToMTA {
my ($msg, $send_now) = (@_);
@@ -93,29 +94,6 @@ sub MessageToMTA {
# thus to hopefully avoid auto replies.
$email->header_set('Auto-Submitted', 'auto-generated');
- $email->walk_parts(sub {
- my ($part) = @_;
- return if $part->parts > 1; # Top-level
- my $content_type = $part->content_type || '';
- $content_type =~ /charset=['"](.+)['"]/;
- # If no charset is defined or is the default us-ascii,
- # then we encode the email to UTF-8 if Bugzilla has utf8 enabled.
- # XXX - This is a hack to workaround bug 723944.
- if (!$1 || $1 eq 'us-ascii') {
- my $body = $part->body;
- if (Bugzilla->params->{'utf8'}) {
- $part->charset_set('UTF-8');
- # encoding_set works only with bytes, not with utf8 strings.
- my $raw = $part->body_raw;
- if (utf8::is_utf8($raw)) {
- utf8::encode($raw);
- $part->body_set($raw);
- }
- }
- $part->encoding_set('quoted-printable') if !is_7bit_clean($body);
- }
- });
-
# MIME-Version must be set otherwise some mailsystems ignore the charset
$email->header_set('MIME-Version', '1.0') if !$email->header('MIME-Version');
@@ -140,7 +118,9 @@ sub MessageToMTA {
my $from = $email->header('From');
my ($hostname, @args);
+ my $mailer_class = $method;
if ($method eq "Sendmail") {
+ $mailer_class = 'Bugzilla::Send::Sendmail';
if (ON_WINDOWS) {
$Email::Send::Sendmail::SENDMAIL = SENDMAIL_EXE;
}
@@ -169,6 +149,12 @@ sub MessageToMTA {
}
}
+ # For tracking/diagnostic purposes, add our hostname
+ my $generated_by = $email->header('X-Generated-By') || '';
+ if ($generated_by =~ tr/\/// < 3) {
+ $email->header_set('X-Generated-By' => $generated_by . '/' . hostname() . "($$)");
+ }
+
if ($method eq "SMTP") {
push @args, Host => Bugzilla->params->{"smtpserver"},
username => Bugzilla->params->{"smtp_username"},
@@ -180,6 +166,32 @@ sub MessageToMTA {
Bugzilla::Hook::process('mailer_before_send',
{ email => $email, mailer_args => \@args });
+ # Allow for extensions to to drop the bugmail by clearing the 'to' header
+ return if $email->header('to') eq '';
+
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ return if $part->parts > 1; # Top-level
+ my $content_type = $part->content_type || '';
+ $content_type =~ /charset=['"](.+)['"]/;
+ # If no charset is defined or is the default us-ascii,
+ # then we encode the email to UTF-8 if Bugzilla has utf8 enabled.
+ # XXX - This is a hack to workaround bug 723944.
+ if (!$1 || $1 eq 'us-ascii') {
+ my $body = $part->body;
+ if (Bugzilla->params->{'utf8'}) {
+ $part->charset_set('UTF-8');
+ # encoding_set works only with bytes, not with utf8 strings.
+ my $raw = $part->body_raw;
+ if (utf8::is_utf8($raw)) {
+ utf8::encode($raw);
+ $part->body_set($raw);
+ }
+ }
+ $part->encoding_set('quoted-printable') if !is_7bit_clean($body);
+ }
+ });
+
if ($method eq "Test") {
my $filename = bz_locations()->{'datadir'} . '/mailer.testfile';
open TESTFILE, '>>', $filename;
@@ -190,7 +202,7 @@ sub MessageToMTA {
else {
# This is useful for both Sendmail and Qmail, so we put it out here.
local $ENV{PATH} = SENDMAIL_PATH;
- my $mailer = Email::Send->new({ mailer => $method,
+ my $mailer = Email::Send->new({ mailer => $mailer_class,
mailer_args => \@args });
my $retval = $mailer->send($email);
ThrowCodeError('mail_send_error', { msg => $retval, mail => $email })
diff --git a/Bugzilla/Migrate.pm b/Bugzilla/Migrate.pm
index ee0dcab95..2027af7d3 100644
--- a/Bugzilla/Migrate.pm
+++ b/Bugzilla/Migrate.pm
@@ -827,7 +827,7 @@ sub _insert_comments {
$self->_do_table_insert('longdescs', \%copy);
$self->debug(" Inserted comment from " . $who->login, 2);
}
- $bug->_sync_fulltext();
+ $bug->_sync_fulltext( update_comments => 1 );
}
sub _insert_history {
diff --git a/Bugzilla/Object.pm b/Bugzilla/Object.pm
index d4574abd2..96651d191 100644
--- a/Bugzilla/Object.pm
+++ b/Bugzilla/Object.pm
@@ -72,6 +72,8 @@ sub new {
sub _init {
my $class = shift;
my ($param) = @_;
+ my $object = $class->_cache_get($param);
+ return $object if $object;
my $dbh = Bugzilla->dbh;
my $columns = join(',', $class->_get_db_columns);
my $table = $class->DB_TABLE;
@@ -82,7 +84,6 @@ sub _init {
if (ref $param eq 'HASH') {
$id = $param->{id};
}
- my $object;
if (defined $id) {
# We special-case if somebody specifies an ID, so that we can
@@ -125,9 +126,48 @@ sub _init {
"SELECT $columns FROM $table WHERE $condition", undef, @values);
}
+ $class->_cache_set($param, $object) if $object;
return $object;
}
+# Provides a mechanism for objects to be cached in the request_cahce
+
+sub _cache_get {
+ my $class = shift;
+ my ($param) = @_;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ return Bugzilla->request_cache->{$cache_key};
+}
+
+sub _cache_set {
+ my $class = shift;
+ my ($param, $object) = @_;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ Bugzilla->request_cache->{$cache_key} = $object;
+}
+
+sub _cache_remove {
+ my $class = shift;
+ my ($param, $object) = @_;
+ $param->{cache} = 1;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ delete Bugzilla->request_cache->{$cache_key};
+}
+
+sub cache_key {
+ my $class = shift;
+ my ($param) = @_;
+ if (ref($param) && $param->{cache} && ($param->{id} || $param->{name})) {
+ $class = blessed($class) if blessed($class);
+ return $class . ',' . ($param->{id} || $param->{name});
+ } else {
+ return;
+ }
+}
+
sub check {
my ($invocant, $param) = @_;
my $class = ref($invocant) || $invocant;
@@ -228,8 +268,11 @@ sub match {
}
next;
}
-
- $class->_check_field($field, 'match');
+
+ # It's always safe to use the field defined by classes as being
+ # their ID field. In particular, this means that new_from_list()
+ # is exempted from this check.
+ $class->_check_field($field, 'match') unless $field eq $class->ID_FIELD;
if (ref $value eq 'ARRAY') {
# IN () is invalid SQL, and if we have an empty list
@@ -332,12 +375,17 @@ sub set_all {
my %field_values = %$params;
my @sorted_names = $self->_sort_by_dep(keys %field_values);
+
foreach my $key (@sorted_names) {
# It's possible for one set_ method to delete a key from $params
# for another set method, so if that's happened, we don't call the
# other set method.
next if !exists $field_values{$key};
my $method = "set_$key";
+ if (!$self->can($method)) {
+ my $class = ref($self) || $self;
+ ThrowCodeError("unknown_method", { method => "${class}::${method}" });
+ }
$self->$method($field_values{$key}, \%field_values);
}
Bugzilla::Hook::process('object_end_of_set_all',
@@ -398,6 +446,7 @@ sub update {
$self->audit_log(\%changes) if $self->AUDIT_UPDATES;
$dbh->bz_commit_transaction();
+ $self->_cache_remove({ id => $self->id });
if (wantarray) {
return (\%changes, $old_self);
@@ -416,6 +465,7 @@ sub remove_from_db {
$self->audit_log(AUDIT_REMOVE) if $self->AUDIT_REMOVES;
$dbh->do("DELETE FROM $table WHERE $id_field = ?", undef, $self->id);
$dbh->bz_commit_transaction();
+ $self->_cache_remove({ id => $self->id });
undef $self;
}
diff --git a/Bugzilla/PatchReader.pm b/Bugzilla/PatchReader.pm
new file mode 100644
index 000000000..b5c3b957b
--- /dev/null
+++ b/Bugzilla/PatchReader.pm
@@ -0,0 +1,117 @@
+package Bugzilla::PatchReader;
+
+use strict;
+
+=head1 NAME
+
+PatchReader - Utilities to read and manipulate patches and CVS
+
+=head1 SYNOPSIS
+
+ # Script that reads in a patch (in any known format), and prints
+ # out some information about it. Other common operations are
+ # outputting the patch in a raw unified diff format, outputting
+ # the patch information to Template::Toolkit templates, adding
+ # context to a patch from CVS, and narrowing the patch down to
+ # apply only to a single file or set of files.
+
+ use PatchReader::Raw;
+ use PatchReader::PatchInfoGrabber;
+ my $filename = 'filename.patch';
+
+ # Create the reader that parses the patch and the object that
+ # extracts info from the reader's datastream
+ my $reader = new PatchReader::Raw();
+ my $patch_info_grabber = new PatchReader::PatchInfoGrabber();
+ $reader->sends_data_to($patch_info_grabber);
+
+ # Iterate over the file
+ $reader->iterate_file($filename);
+
+ # Print the output
+ my $patch_info = $patch_info_grabber->patch_info();
+ print "Summary of Changed Files:\n";
+ while (my ($file, $info) = each %{$patch_info->{files}}) {
+ print "$file: +$info->{plus_lines} -$info->{minus_lines}\n";
+ }
+
+=head1 ABSTRACT
+
+This perl library allows you to manipulate patches programmatically by
+chaining together a variety of objects that read, manipulate, and output
+patch information:
+
+=over
+
+=item PatchReader::Raw
+
+Parse a patch in any format known to this author (unified, normal, cvs diff,
+among others)
+
+=item PatchReader::PatchInfoGrabber
+
+Grab summary info for sections of a patch in a nice hash
+
+=item PatchReader::AddCVSContext
+
+Add context to the patch by grabbing the original files from CVS
+
+=item PatchReader::NarrowPatch
+
+Narrow a patch down to only apply to a specific set of files
+
+=item PatchReader::DiffPrinter::raw
+
+Output the parsed patch in raw unified diff format
+
+=item PatchReader::DiffPrinter::template
+
+Output the parsed patch to L<Template::Toolkit> templates (can be used to make
+HTML output or anything else you please)
+
+=back
+
+Additionally, it is designed so that you can plug in your own objects that
+read the parsed data while it is being parsed (no need for the performance or
+memory problems that can come from reading in the entire patch all at once).
+You can do this by mimicking one of the existing readers (such as
+PatchInfoGrabber) and overriding the methods start_patch, start_file, section,
+end_file and end_patch.
+
+=head1 AUTHORS
+
+ John Keiser <jkeiser@cpan.org>
+ Teemu Mannermaa <tmannerm@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+ Copyright (C) 2003-2004, John Keiser and
+ Copyright (C) 2011-2012, Teemu Mannermaa.
+
+This module is free software; you can redistribute it and/or modify it under
+the terms of the Artistic License 1.0. For details, see the full text of the
+license at
+ <http://www.perlfoundation.org/artistic_license_1_0>.
+
+This module is distributed in the hope that it will be useful, but it is
+provided “as is” and without any warranty; without even the implied warranty
+of merchantability or fitness for a particular purpose.
+
+Files with different licenses or copyright holders:
+
+=over
+
+=item F<lib/PatchReader/CVSClient.pm>
+
+Portions created by Netscape are
+Copyright (C) 2003, Netscape Communications Corporation. All rights reserved.
+
+This file is subject to the terms of the Mozilla Public License, v. 2.0.
+
+=back
+
+=cut
+
+$Bugzilla::PatchReader::VERSION = '0.9.7';
+
+1
diff --git a/Bugzilla/PatchReader/AddCVSContext.pm b/Bugzilla/PatchReader/AddCVSContext.pm
new file mode 100644
index 000000000..910e45669
--- /dev/null
+++ b/Bugzilla/PatchReader/AddCVSContext.pm
@@ -0,0 +1,226 @@
+package Bugzilla::PatchReader::AddCVSContext;
+
+use Bugzilla::PatchReader::FilterPatch;
+use Bugzilla::PatchReader::CVSClient;
+use Cwd;
+use File::Temp;
+
+use strict;
+
+@Bugzilla::PatchReader::AddCVSContext::ISA = qw(Bugzilla::PatchReader::FilterPatch);
+
+# XXX If you need to, get the entire patch worth of files and do a single
+# cvs update of all files as soon as you find a file where you need to do a
+# cvs update, to avoid the significant connect overhead
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ $this->{CONTEXT} = $_[0];
+ $this->{CVSROOT} = $_[1];
+
+ return $this;
+}
+
+sub my_rmtree {
+ my ($this, $dir) = @_;
+ foreach my $file (glob("$dir/*")) {
+ if (-d $file) {
+ $this->my_rmtree($file);
+ } else {
+ trick_taint($file);
+ unlink $file;
+ }
+ }
+ trick_taint($dir);
+ rmdir $dir;
+}
+
+sub end_patch {
+ my $this = shift;
+ if (exists($this->{TMPDIR})) {
+ # Set as variable to get rid of taint
+ # One would like to use rmtree here, but that is not taint-safe.
+ $this->my_rmtree($this->{TMPDIR});
+ }
+}
+
+sub start_file {
+ my $this = shift;
+ my ($file) = @_;
+ $this->{HAS_CVS_CONTEXT} = !$file->{is_add} && !$file->{is_remove} &&
+ $file->{old_revision};
+ $this->{REVISION} = $file->{old_revision};
+ $this->{FILENAME} = $file->{filename};
+ $this->{SECTION_END} = -1;
+ $this->{TARGET}->start_file(@_) if $this->{TARGET};
+}
+
+sub end_file {
+ my $this = shift;
+ $this->flush_section();
+
+ if ($this->{FILE}) {
+ close $this->{FILE};
+ unlink $this->{FILE}; # If it fails, it fails ...
+ delete $this->{FILE};
+ }
+ $this->{TARGET}->end_file(@_) if $this->{TARGET};
+}
+
+sub next_section {
+ my $this = shift;
+ my ($section) = @_;
+ $this->{NEXT_PATCH_LINE} = $section->{old_start};
+ $this->{NEXT_NEW_LINE} = $section->{new_start};
+ foreach my $line (@{$section->{lines}}) {
+ # If this is a line requiring context ...
+ if ($line =~ /^[-\+]/) {
+ # Determine how much context is needed for both the previous section line
+ # and this one:
+ # - If there is no old line, start new section
+ # - If this is file context, add (old section end to new line) context to
+ # the existing section
+ # - If old end context line + 1 < new start context line, there is an empty
+ # space and therefore we end the old section and start the new one
+ # - Else we add (old start context line through new line) context to
+ # existing section
+ if (! exists($this->{SECTION})) {
+ $this->_start_section();
+ } elsif ($this->{CONTEXT} eq "file") {
+ $this->push_context_lines($this->{SECTION_END} + 1,
+ $this->{NEXT_PATCH_LINE} - 1);
+ } else {
+ my $start_context = $this->{NEXT_PATCH_LINE} - $this->{CONTEXT};
+ $start_context = $start_context > 0 ? $start_context : 0;
+ if (($this->{SECTION_END} + $this->{CONTEXT} + 1) < $start_context) {
+ $this->flush_section();
+ $this->_start_section();
+ } else {
+ $this->push_context_lines($this->{SECTION_END} + 1,
+ $this->{NEXT_PATCH_LINE} - 1);
+ }
+ }
+ push @{$this->{SECTION}{lines}}, $line;
+ if (substr($line, 0, 1) eq "+") {
+ $this->{SECTION}{plus_lines}++;
+ $this->{SECTION}{new_lines}++;
+ $this->{NEXT_NEW_LINE}++;
+ } else {
+ $this->{SECTION_END}++;
+ $this->{SECTION}{minus_lines}++;
+ $this->{SECTION}{old_lines}++;
+ $this->{NEXT_PATCH_LINE}++;
+ }
+ } else {
+ $this->{NEXT_PATCH_LINE}++;
+ $this->{NEXT_NEW_LINE}++;
+ }
+ # If this is context, for now lose it (later we should try and determine if
+ # we can just use it instead of pulling the file all the time)
+ }
+}
+
+sub determine_start {
+ my ($this, $line) = @_;
+ return 0 if $line < 0;
+ if ($this->{CONTEXT} eq "file") {
+ return 1;
+ } else {
+ my $start = $line - $this->{CONTEXT};
+ $start = $start > 0 ? $start : 1;
+ return $start;
+ }
+}
+
+sub _start_section {
+ my $this = shift;
+
+ # Add the context to the beginning
+ $this->{SECTION}{old_start} = $this->determine_start($this->{NEXT_PATCH_LINE});
+ $this->{SECTION}{new_start} = $this->determine_start($this->{NEXT_NEW_LINE});
+ $this->{SECTION}{old_lines} = 0;
+ $this->{SECTION}{new_lines} = 0;
+ $this->{SECTION}{minus_lines} = 0;
+ $this->{SECTION}{plus_lines} = 0;
+ $this->{SECTION_END} = $this->{SECTION}{old_start} - 1;
+ $this->push_context_lines($this->{SECTION}{old_start},
+ $this->{NEXT_PATCH_LINE} - 1);
+}
+
+sub flush_section {
+ my $this = shift;
+
+ if ($this->{SECTION}) {
+ # Add the necessary context to the end
+ if ($this->{CONTEXT} eq "file") {
+ $this->push_context_lines($this->{SECTION_END} + 1, "file");
+ } else {
+ $this->push_context_lines($this->{SECTION_END} + 1,
+ $this->{SECTION_END} + $this->{CONTEXT});
+ }
+ # Send the section and line notifications
+ $this->{TARGET}->next_section($this->{SECTION}) if $this->{TARGET};
+ delete $this->{SECTION};
+ $this->{SECTION_END} = 0;
+ }
+}
+
+sub push_context_lines {
+ my $this = shift;
+ # Grab from start to end
+ my ($start, $end) = @_;
+ return if $end ne "file" && $start > $end;
+
+ # If it's an added / removed file, don't do anything
+ return if ! $this->{HAS_CVS_CONTEXT};
+
+ # Get and open the file if necessary
+ if (!$this->{FILE}) {
+ my $olddir = getcwd();
+ if (! exists($this->{TMPDIR})) {
+ $this->{TMPDIR} = File::Temp::tempdir();
+ if (! -d $this->{TMPDIR}) {
+ die "Could not get temporary directory";
+ }
+ }
+ chdir($this->{TMPDIR}) or die "Could not cd $this->{TMPDIR}";
+ if (Bugzilla::PatchReader::CVSClient::cvs_co_rev($this->{CVSROOT}, $this->{REVISION}, $this->{FILENAME})) {
+ die "Could not check out $this->{FILENAME} r$this->{REVISION} from $this->{CVSROOT}";
+ }
+ open my $fh, $this->{FILENAME} or die "Could not open $this->{FILENAME}";
+ $this->{FILE} = $fh;
+ $this->{NEXT_FILE_LINE} = 1;
+ trick_taint($olddir); # $olddir comes from getcwd()
+ chdir($olddir) or die "Could not cd back to $olddir";
+ }
+
+ # Read through the file to reach the line we need
+ die "File read too far!" if $this->{NEXT_FILE_LINE} && $this->{NEXT_FILE_LINE} > $start;
+ my $fh = $this->{FILE};
+ while ($this->{NEXT_FILE_LINE} < $start) {
+ my $dummy = <$fh>;
+ $this->{NEXT_FILE_LINE}++;
+ }
+ my $i = $start;
+ for (; $end eq "file" || $i <= $end; $i++) {
+ my $line = <$fh>;
+ last if !defined($line);
+ $line =~ s/\r\n/\n/g;
+ push @{$this->{SECTION}{lines}}, " $line";
+ $this->{NEXT_FILE_LINE}++;
+ $this->{SECTION}{old_lines}++;
+ $this->{SECTION}{new_lines}++;
+ }
+ $this->{SECTION_END} = $i - 1;
+}
+
+sub trick_taint {
+ $_[0] =~ /^(.*)$/s;
+ $_[0] = $1;
+ return (defined($_[0]));
+}
+
+1;
diff --git a/Bugzilla/PatchReader/Base.pm b/Bugzilla/PatchReader/Base.pm
new file mode 100644
index 000000000..f2fd69a68
--- /dev/null
+++ b/Bugzilla/PatchReader/Base.pm
@@ -0,0 +1,23 @@
+package Bugzilla::PatchReader::Base;
+
+use strict;
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = {};
+ bless $this, $class;
+
+ return $this;
+}
+
+sub sends_data_to {
+ my $this = shift;
+ if (defined($_[0])) {
+ $this->{TARGET} = $_[0];
+ } else {
+ return $this->{TARGET};
+ }
+}
+
+1
diff --git a/Bugzilla/PatchReader/CVSClient.pm b/Bugzilla/PatchReader/CVSClient.pm
new file mode 100644
index 000000000..2f76fc18d
--- /dev/null
+++ b/Bugzilla/PatchReader/CVSClient.pm
@@ -0,0 +1,48 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::PatchReader::CVSClient;
+
+use strict;
+
+sub parse_cvsroot {
+ my $cvsroot = $_[0];
+ # Format: :method:[user[:password]@]server[:[port]]/path
+ if ($cvsroot =~ /^:([^:]*):(.*?)(\/.*)$/) {
+ my %retval;
+ $retval{protocol} = $1;
+ $retval{rootdir} = $3;
+ my $remote = $2;
+ if ($remote =~ /^(([^\@:]*)(:([^\@]*))?\@)?([^:]*)(:(.*))?$/) {
+ $retval{user} = $2;
+ $retval{password} = $4;
+ $retval{server} = $5;
+ $retval{port} = $7;
+ return %retval;
+ }
+ }
+
+ return (
+ rootdir => $cvsroot
+ );
+}
+
+sub cvs_co {
+ my ($cvsroot, @files) = @_;
+ my $cvs = $::cvsbin || "cvs";
+ return system($cvs, "-Q", "-d$cvsroot", "co", @files);
+}
+
+sub cvs_co_rev {
+ my ($cvsroot, $rev, @files) = @_;
+ my $cvs = $::cvsbin || "cvs";
+ return system($cvs, "-Q", "-d$cvsroot", "co", "-r$rev", @files);
+}
+
+1
diff --git a/Bugzilla/PatchReader/DiffPrinter/raw.pm b/Bugzilla/PatchReader/DiffPrinter/raw.pm
new file mode 100644
index 000000000..ceb425800
--- /dev/null
+++ b/Bugzilla/PatchReader/DiffPrinter/raw.pm
@@ -0,0 +1,61 @@
+package Bugzilla::PatchReader::DiffPrinter::raw;
+
+use strict;
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = {};
+ bless $this, $class;
+
+ $this->{OUTFILE} = @_ ? $_[0] : *STDOUT;
+ my $fh = $this->{OUTFILE};
+
+ return $this;
+}
+
+sub start_patch {
+}
+
+sub end_patch {
+}
+
+sub start_file {
+ my $this = shift;
+ my ($file) = @_;
+
+ my $fh = $this->{OUTFILE};
+ if ($file->{rcs_filename}) {
+ print $fh "Index: $file->{filename}\n";
+ print $fh "===================================================================\n";
+ print $fh "RCS file: $file->{rcs_filename}\n";
+ }
+ my $old_file = $file->{is_add} ? "/dev/null" : $file->{filename};
+ my $old_date = $file->{old_date_str} || "";
+ print $fh "--- $old_file\t$old_date";
+ print $fh "\t$file->{old_revision}" if $file->{old_revision};
+ print $fh "\n";
+ my $new_file = $file->{is_remove} ? "/dev/null" : $file->{filename};
+ my $new_date = $file->{new_date_str} || "";
+ print $fh "+++ $new_file\t$new_date";
+ print $fh "\t$file->{new_revision}" if $file->{new_revision};
+ print $fh "\n";
+}
+
+sub end_file {
+}
+
+sub next_section {
+ my $this = shift;
+ my ($section) = @_;
+
+ return unless $section->{old_start} || $section->{new_start};
+ my $fh = $this->{OUTFILE};
+ print $fh "@@ -$section->{old_start},$section->{old_lines} +$section->{new_start},$section->{new_lines} @@ $section->{func_info}\n";
+ foreach my $line (@{$section->{lines}}) {
+ $line =~ s/(\r?\n?)$/\n/;
+ print $fh $line;
+ }
+}
+
+1
diff --git a/Bugzilla/PatchReader/DiffPrinter/template.pm b/Bugzilla/PatchReader/DiffPrinter/template.pm
new file mode 100644
index 000000000..6545e9336
--- /dev/null
+++ b/Bugzilla/PatchReader/DiffPrinter/template.pm
@@ -0,0 +1,119 @@
+package Bugzilla::PatchReader::DiffPrinter::template;
+
+use strict;
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = {};
+ bless $this, $class;
+
+ $this->{TEMPLATE_PROCESSOR} = $_[0];
+ $this->{HEADER_TEMPLATE} = $_[1];
+ $this->{FILE_TEMPLATE} = $_[2];
+ $this->{FOOTER_TEMPLATE} = $_[3];
+ $this->{ARGS} = $_[4] || {};
+
+ $this->{ARGS}{file_count} = 0;
+ return $this;
+}
+
+sub start_patch {
+ my $this = shift;
+ $this->{TEMPLATE_PROCESSOR}->process($this->{HEADER_TEMPLATE}, $this->{ARGS})
+ || ::ThrowTemplateError($this->{TEMPLATE_PROCESSOR}->error());
+}
+
+sub end_patch {
+ my $this = shift;
+ $this->{TEMPLATE_PROCESSOR}->process($this->{FOOTER_TEMPLATE}, $this->{ARGS})
+ || ::ThrowTemplateError($this->{TEMPLATE_PROCESSOR}->error());
+}
+
+sub start_file {
+ my $this = shift;
+ $this->{ARGS}{file_count}++;
+ $this->{ARGS}{file} = shift;
+ $this->{ARGS}{file}{plus_lines} = 0;
+ $this->{ARGS}{file}{minus_lines} = 0;
+ @{$this->{ARGS}{sections}} = ();
+}
+
+sub end_file {
+ my $this = shift;
+ my $file = $this->{ARGS}{file};
+ if ($file->{canonical} && $file->{old_revision} && $this->{ARGS}{bonsai_url}) {
+ $this->{ARGS}{bonsai_prefix} = "$this->{ARGS}{bonsai_url}/cvsblame.cgi?file=$file->{filename}&amp;rev=$file->{old_revision}";
+ }
+ if ($file->{canonical} && $this->{ARGS}{lxr_url}) {
+ # Cut off the lxr root, if any
+ my $filename = $file->{filename};
+ $filename = substr($filename, length($this->{ARGS}{lxr_root}));
+ $this->{ARGS}{lxr_prefix} = "$this->{ARGS}{lxr_url}/source/$filename";
+ }
+
+ $this->{TEMPLATE_PROCESSOR}->process($this->{FILE_TEMPLATE}, $this->{ARGS})
+ || ::ThrowTemplateError($this->{TEMPLATE_PROCESSOR}->error());
+ @{$this->{ARGS}{sections}} = ();
+ delete $this->{ARGS}{file};
+}
+
+sub next_section {
+ my $this = shift;
+ my ($section) = @_;
+
+ $this->{ARGS}{file}{plus_lines} += $section->{plus_lines};
+ $this->{ARGS}{file}{minus_lines} += $section->{minus_lines};
+
+ # Get groups of lines and print them
+ my $last_line_char = '';
+ my $context_lines = [];
+ my $plus_lines = [];
+ my $minus_lines = [];
+ foreach my $line (@{$section->{lines}}) {
+ $line =~ s/\r?\n?$//;
+ if ($line =~ /^ /) {
+ if ($last_line_char ne ' ') {
+ push @{$section->{groups}}, {context => $context_lines,
+ plus => $plus_lines,
+ minus => $minus_lines};
+ $context_lines = [];
+ $plus_lines = [];
+ $minus_lines = [];
+ }
+ $last_line_char = ' ';
+ push @{$context_lines}, substr($line, 1);
+ } elsif ($line =~ /^\+/) {
+ if ($last_line_char eq ' ' || $last_line_char eq '-' && @{$plus_lines}) {
+ push @{$section->{groups}}, {context => $context_lines,
+ plus => $plus_lines,
+ minus => $minus_lines};
+ $context_lines = [];
+ $plus_lines = [];
+ $minus_lines = [];
+ $last_line_char = '';
+ }
+ $last_line_char = '+';
+ push @{$plus_lines}, substr($line, 1);
+ } elsif ($line =~ /^-/) {
+ if ($last_line_char eq '+' && @{$minus_lines}) {
+ push @{$section->{groups}}, {context => $context_lines,
+ plus => $plus_lines,
+ minus => $minus_lines};
+ $context_lines = [];
+ $plus_lines = [];
+ $minus_lines = [];
+ $last_line_char = '';
+ }
+ $last_line_char = '-';
+ push @{$minus_lines}, substr($line, 1);
+ }
+ }
+
+ push @{$section->{groups}}, {context => $context_lines,
+ plus => $plus_lines,
+ minus => $minus_lines};
+ push @{$this->{ARGS}{sections}}, $section;
+}
+
+1
diff --git a/Bugzilla/PatchReader/FilterPatch.pm b/Bugzilla/PatchReader/FilterPatch.pm
new file mode 100644
index 000000000..dfe42e750
--- /dev/null
+++ b/Bugzilla/PatchReader/FilterPatch.pm
@@ -0,0 +1,43 @@
+package Bugzilla::PatchReader::FilterPatch;
+
+use strict;
+
+use Bugzilla::PatchReader::Base;
+
+@Bugzilla::PatchReader::FilterPatch::ISA = qw(Bugzilla::PatchReader::Base);
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ return $this;
+}
+
+sub start_patch {
+ my $this = shift;
+ $this->{TARGET}->start_patch(@_) if $this->{TARGET};
+}
+
+sub end_patch {
+ my $this = shift;
+ $this->{TARGET}->end_patch(@_) if $this->{TARGET};
+}
+
+sub start_file {
+ my $this = shift;
+ $this->{TARGET}->start_file(@_) if $this->{TARGET};
+}
+
+sub end_file {
+ my $this = shift;
+ $this->{TARGET}->end_file(@_) if $this->{TARGET};
+}
+
+sub next_section {
+ my $this = shift;
+ $this->{TARGET}->next_section(@_) if $this->{TARGET};
+}
+
+1
diff --git a/Bugzilla/PatchReader/FixPatchRoot.pm b/Bugzilla/PatchReader/FixPatchRoot.pm
new file mode 100644
index 000000000..e67fb2796
--- /dev/null
+++ b/Bugzilla/PatchReader/FixPatchRoot.pm
@@ -0,0 +1,130 @@
+package Bugzilla::PatchReader::FixPatchRoot;
+
+use Bugzilla::PatchReader::FilterPatch;
+use Bugzilla::PatchReader::CVSClient;
+
+use strict;
+
+@Bugzilla::PatchReader::FixPatchRoot::ISA = qw(Bugzilla::PatchReader::FilterPatch);
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ my %parsed = Bugzilla::PatchReader::CVSClient::parse_cvsroot($_[0]);
+ $this->{REPOSITORY_ROOT} = $parsed{rootdir};
+ $this->{REPOSITORY_ROOT} .= "/" if substr($this->{REPOSITORY_ROOT}, -1) ne "/";
+
+ return $this;
+}
+
+sub diff_root {
+ my $this = shift;
+ if (@_) {
+ $this->{DIFF_ROOT} = $_[0];
+ } else {
+ return $this->{DIFF_ROOT};
+ }
+}
+
+sub flush_delayed_commands {
+ my $this = shift;
+ return if ! $this->{DELAYED_COMMANDS};
+
+ my $commands = $this->{DELAYED_COMMANDS};
+ delete $this->{DELAYED_COMMANDS};
+ $this->{FORCE_COMMANDS} = 1;
+ foreach my $command_arr (@{$commands}) {
+ my $command = $command_arr->[0];
+ my $arg = $command_arr->[1];
+ if ($command eq "start_file") {
+ $this->start_file($arg);
+ } elsif ($command eq "end_file") {
+ $this->end_file($arg);
+ } elsif ($command eq "section") {
+ $this->next_section($arg);
+ }
+ }
+}
+
+sub end_patch {
+ my $this = shift;
+ $this->flush_delayed_commands();
+ $this->{TARGET}->end_patch(@_) if $this->{TARGET};
+}
+
+sub start_file {
+ my $this = shift;
+ my ($file) = @_;
+ # If the file is new, it will not have a filename that fits the repository
+ # root and therefore needs to be fixed up to have the same root as everyone
+ # else. At the same time we need to fix DIFF_ROOT too.
+ if (exists($this->{DIFF_ROOT})) {
+ # XXX Return error if there are multiple roots in the patch by verifying
+ # that the DIFF_ROOT is not different from the calculated diff root on this
+ # filename
+
+ $file->{filename} = $this->{DIFF_ROOT} . $file->{filename};
+
+ $file->{canonical} = 1;
+ } elsif ($file->{rcs_filename} &&
+ substr($file->{rcs_filename}, 0, length($this->{REPOSITORY_ROOT})) eq
+ $this->{REPOSITORY_ROOT}) {
+ # Since we know the repository we can determine where the user was in the
+ # repository when they did the diff by chopping off the repository root
+ # from the rcs filename
+ $this->{DIFF_ROOT} = substr($file->{rcs_filename},
+ length($this->{REPOSITORY_ROOT}));
+ $this->{DIFF_ROOT} =~ s/,v$//;
+ # If the RCS file exists in the Attic then we need to correct for
+ # this, stripping off the '/Attic' suffix in order to reduce the name
+ # to just the CVS root.
+ if ($this->{DIFF_ROOT} =~ m/Attic/) {
+ $this->{DIFF_ROOT} = substr($this->{DIFF_ROOT}, 0, -6);
+ }
+ # XXX More error checking--that filename exists and that it is in fact
+ # part of the rcs filename
+ $this->{DIFF_ROOT} = substr($this->{DIFF_ROOT}, 0,
+ -length($file->{filename}));
+ $this->flush_delayed_commands();
+
+ $file->{filename} = $this->{DIFF_ROOT} . $file->{filename};
+
+ $file->{canonical} = 1;
+ } else {
+ # DANGER Will Robinson. The first file in the patch is new. We will try
+ # "delayed command mode"
+ #
+ # (if force commands is on we are already in delayed command mode, and sadly
+ # this means the entire patch was unintelligible to us, so we just output
+ # whatever the hell was in the patch)
+
+ if (!$this->{FORCE_COMMANDS}) {
+ push @{$this->{DELAYED_COMMANDS}}, [ "start_file", { %{$file} } ];
+ return;
+ }
+ }
+ $this->{TARGET}->start_file($file) if $this->{TARGET};
+}
+
+sub end_file {
+ my $this = shift;
+ if (exists($this->{DELAYED_COMMANDS})) {
+ push @{$this->{DELAYED_COMMANDS}}, [ "end_file", { %{$_[0]} } ];
+ } else {
+ $this->{TARGET}->end_file(@_) if $this->{TARGET};
+ }
+}
+
+sub next_section {
+ my $this = shift;
+ if (exists($this->{DELAYED_COMMANDS})) {
+ push @{$this->{DELAYED_COMMANDS}}, [ "section", { %{$_[0]} } ];
+ } else {
+ $this->{TARGET}->next_section(@_) if $this->{TARGET};
+ }
+}
+
+1
diff --git a/Bugzilla/PatchReader/NarrowPatch.pm b/Bugzilla/PatchReader/NarrowPatch.pm
new file mode 100644
index 000000000..b6502f2f3
--- /dev/null
+++ b/Bugzilla/PatchReader/NarrowPatch.pm
@@ -0,0 +1,44 @@
+package Bugzilla::PatchReader::NarrowPatch;
+
+use Bugzilla::PatchReader::FilterPatch;
+
+use strict;
+
+@Bugzilla::PatchReader::NarrowPatch::ISA = qw(Bugzilla::PatchReader::FilterPatch);
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ $this->{INCLUDE_FILES} = [@_];
+
+ return $this;
+}
+
+sub start_file {
+ my $this = shift;
+ my ($file) = @_;
+ if (grep { $_ eq substr($file->{filename}, 0, length($_)) } @{$this->{INCLUDE_FILES}}) {
+ $this->{IS_INCLUDED} = 1;
+ $this->{TARGET}->start_file(@_) if $this->{TARGET};
+ }
+}
+
+sub end_file {
+ my $this = shift;
+ if ($this->{IS_INCLUDED}) {
+ $this->{TARGET}->end_file(@_) if $this->{TARGET};
+ $this->{IS_INCLUDED} = 0;
+ }
+}
+
+sub next_section {
+ my $this = shift;
+ if ($this->{IS_INCLUDED}) {
+ $this->{TARGET}->next_section(@_) if $this->{TARGET};
+ }
+}
+
+1
diff --git a/Bugzilla/PatchReader/PatchInfoGrabber.pm b/Bugzilla/PatchReader/PatchInfoGrabber.pm
new file mode 100644
index 000000000..8c52931ba
--- /dev/null
+++ b/Bugzilla/PatchReader/PatchInfoGrabber.pm
@@ -0,0 +1,45 @@
+package Bugzilla::PatchReader::PatchInfoGrabber;
+
+use Bugzilla::PatchReader::FilterPatch;
+
+use strict;
+
+@Bugzilla::PatchReader::PatchInfoGrabber::ISA = qw(Bugzilla::PatchReader::FilterPatch);
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ return $this;
+}
+
+sub patch_info {
+ my $this = shift;
+ return $this->{PATCH_INFO};
+}
+
+sub start_patch {
+ my $this = shift;
+ $this->{PATCH_INFO} = {};
+ $this->{TARGET}->start_patch(@_) if $this->{TARGET};
+}
+
+sub start_file {
+ my $this = shift;
+ my ($file) = @_;
+ $this->{PATCH_INFO}{files}{$file->{filename}} = { %{$file} };
+ $this->{FILE} = { %{$file} };
+ $this->{TARGET}->start_file(@_) if $this->{TARGET};
+}
+
+sub next_section {
+ my $this = shift;
+ my ($section) = @_;
+ $this->{PATCH_INFO}{files}{$this->{FILE}{filename}}{plus_lines} += $section->{plus_lines};
+ $this->{PATCH_INFO}{files}{$this->{FILE}{filename}}{minus_lines} += $section->{minus_lines};
+ $this->{TARGET}->next_section(@_) if $this->{TARGET};
+}
+
+1
diff --git a/Bugzilla/PatchReader/Raw.pm b/Bugzilla/PatchReader/Raw.pm
new file mode 100644
index 000000000..b58ed3a2d
--- /dev/null
+++ b/Bugzilla/PatchReader/Raw.pm
@@ -0,0 +1,268 @@
+package Bugzilla::PatchReader::Raw;
+
+#
+# USAGE:
+# use PatchReader::Raw;
+# my $parser = new PatchReader::Raw();
+# $parser->sends_data_to($my_target);
+# $parser->start_lines();
+# open FILE, "mypatch.patch";
+# while (<FILE>) {
+# $parser->next_line($_);
+# }
+# $parser->end_lines();
+#
+
+use strict;
+
+use Bugzilla::PatchReader::Base;
+
+@Bugzilla::PatchReader::Raw::ISA = qw(Bugzilla::PatchReader::Base);
+
+sub new {
+ my $class = shift;
+ $class = ref($class) || $class;
+ my $this = $class->SUPER::new();
+ bless $this, $class;
+
+ return $this;
+}
+
+# We send these notifications:
+# start_patch({ patchname })
+# start_file({ filename, rcs_filename, old_revision, old_date_str, new_revision, new_date_str, is_add, is_remove })
+# next_section({ old_start, new_start, old_lines, new_lines, @lines })
+# end_patch
+# end_file
+sub next_line {
+ my $this = shift;
+ my ($line) = @_;
+
+ return if $line =~ /^\?/;
+
+ # patch header parsing
+ if ($line =~ /^---\s*([\S ]+)\s*\t([^\t\r\n]*)\s*(\S*)/) {
+ $this->_maybe_end_file();
+
+ if ($1 eq "/dev/null") {
+ $this->{FILE_STATE}{is_add} = 1;
+ } else {
+ $this->{FILE_STATE}{filename} = $1;
+ }
+ $this->{FILE_STATE}{old_date_str} = $2;
+ $this->{FILE_STATE}{old_revision} = $3 if $3;
+
+ $this->{IN_HEADER} = 1;
+
+ } elsif ($line =~ /^\+\+\+\s*([\S ]+)\s*\t([^\t\r\n]*)(\S*)/) {
+ if ($1 eq "/dev/null") {
+ $this->{FILE_STATE}{is_remove} = 1;
+ }
+ $this->{FILE_STATE}{new_date_str} = $2;
+ $this->{FILE_STATE}{new_revision} = $3 if $3;
+
+ $this->{IN_HEADER} = 1;
+
+ } elsif ($line =~ /^RCS file: ([\S ]+)/) {
+ $this->{FILE_STATE}{rcs_filename} = $1;
+
+ $this->{IN_HEADER} = 1;
+
+ } elsif ($line =~ /^retrieving revision (\S+)/) {
+ $this->{FILE_STATE}{old_revision} = $1;
+
+ $this->{IN_HEADER} = 1;
+
+ } elsif ($line =~ /^Index:\s*([\S ]+)/) {
+ $this->_maybe_end_file();
+
+ $this->{FILE_STATE}{filename} = $1;
+
+ $this->{IN_HEADER} = 1;
+
+ } elsif ($line =~ /^diff\s*(-\S+\s*)*(\S+)\s*(\S*)/ && $3) {
+ # Simple diff <dir> <dir>
+ $this->_maybe_end_file();
+ $this->{FILE_STATE}{filename} = $2;
+
+ $this->{IN_HEADER} = 1;
+
+ # section parsing
+ } elsif ($line =~ /^@@\s*-(\d+),?(\d*)\s*\+(\d+),?(\d*)\s*(?:@@\s*(.*))?/) {
+ $this->{IN_HEADER} = 0;
+
+ $this->_maybe_start_file();
+ $this->_maybe_end_section();
+ $2 = 0 if !defined($2);
+ $4 = 0 if !defined($4);
+ $this->{SECTION_STATE} = { old_start => $1, old_lines => $2,
+ new_start => $3, new_lines => $4,
+ func_info => $5,
+ minus_lines => 0, plus_lines => 0,
+ };
+
+ } elsif ($line =~ /^(\d+),?(\d*)([acd])(\d+),?(\d*)/) {
+ # Non-universal diff. Calculate as though it were universal.
+ $this->{IN_HEADER} = 0;
+
+ $this->_maybe_start_file();
+ $this->_maybe_end_section();
+
+ my $old_start;
+ my $old_lines;
+ my $new_start;
+ my $new_lines;
+ if ($3 eq 'a') {
+ # 'a' has the old number one off from diff -u ("insert after this line"
+ # vs. "insert at this line")
+ $old_start = $1 + 1;
+ $old_lines = 0;
+ } else {
+ $old_start = $1;
+ $old_lines = $2 ? ($2 - $1 + 1) : 1;
+ }
+ if ($3 eq 'd') {
+ # 'd' has the new number one off from diff -u ("delete after this line"
+ # vs. "delete at this line")
+ $new_start = $4 + 1;
+ $new_lines = 0;
+ } else {
+ $new_start = $4;
+ $new_lines = $5 ? ($5 - $4 + 1) : 1;
+ }
+
+ $this->{SECTION_STATE} = { old_start => $old_start, old_lines => $old_lines,
+ new_start => $new_start, new_lines => $new_lines,
+ minus_lines => 0, plus_lines => 0
+ };
+ }
+
+ # line parsing (only when inside a section)
+ return if $this->{IN_HEADER};
+ if ($line =~ /^ /) {
+ push @{$this->{SECTION_STATE}{lines}}, $line;
+ } elsif ($line =~ /^-/) {
+ $this->{SECTION_STATE}{minus_lines}++;
+ push @{$this->{SECTION_STATE}{lines}}, $line;
+ } elsif ($line =~ /^\+/) {
+ $this->{SECTION_STATE}{plus_lines}++;
+ push @{$this->{SECTION_STATE}{lines}}, $line;
+ } elsif ($line =~ /^< /) {
+ $this->{SECTION_STATE}{minus_lines}++;
+ push @{$this->{SECTION_STATE}{lines}}, "-" . substr($line, 2);
+ } elsif ($line =~ /^> /) {
+ $this->{SECTION_STATE}{plus_lines}++;
+ push @{$this->{SECTION_STATE}{lines}}, "+" . substr($line, 2);
+ }
+}
+
+sub start_lines {
+ my $this = shift;
+ die "No target specified: call sends_data_to!" if !$this->{TARGET};
+ delete $this->{FILE_STARTED};
+ delete $this->{FILE_STATE};
+ delete $this->{SECTION_STATE};
+ $this->{FILE_NEVER_STARTED} = 1;
+
+ $this->{TARGET}->start_patch(@_);
+}
+
+sub end_lines {
+ my $this = shift;
+ $this->_maybe_end_file();
+ $this->{TARGET}->end_patch(@_);
+}
+
+sub _init_state {
+ my $this = shift;
+ $this->{SECTION_STATE}{minus_lines} ||= 0;
+ $this->{SECTION_STATE}{plus_lines} ||= 0;
+}
+
+sub _maybe_start_file {
+ my $this = shift;
+ $this->_init_state();
+ if (exists($this->{FILE_STATE}) && !$this->{FILE_STARTED} ||
+ $this->{FILE_NEVER_STARTED}) {
+ $this->_start_file();
+ }
+}
+
+sub _maybe_end_file {
+ my $this = shift;
+ $this->_init_state();
+ return if $this->{IN_HEADER};
+
+ $this->_maybe_end_section();
+ if (exists($this->{FILE_STATE})) {
+ # Handle empty patch sections (if the file has not been started and we're
+ # already trying to end it, start it first!)
+ if (!$this->{FILE_STARTED}) {
+ $this->_start_file();
+ }
+
+ # Send end notification and set state
+ $this->{TARGET}->end_file($this->{FILE_STATE});
+ delete $this->{FILE_STATE};
+ delete $this->{FILE_STARTED};
+ }
+}
+
+sub _start_file {
+ my $this = shift;
+
+ # Send start notification and set state
+ if (!$this->{FILE_STATE}) {
+ $this->{FILE_STATE} = { filename => "file_not_specified_in_diff" };
+ }
+
+ # Send start notification and set state
+ $this->{TARGET}->start_file($this->{FILE_STATE});
+ $this->{FILE_STARTED} = 1;
+ delete $this->{FILE_NEVER_STARTED};
+}
+
+sub _maybe_end_section {
+ my $this = shift;
+ if (exists($this->{SECTION_STATE})) {
+ $this->{TARGET}->next_section($this->{SECTION_STATE});
+ delete $this->{SECTION_STATE};
+ }
+}
+
+sub iterate_file {
+ my $this = shift;
+ my ($filename) = @_;
+
+ open FILE, $filename or die "Could not open $filename: $!";
+ $this->start_lines($filename);
+ while (<FILE>) {
+ $this->next_line($_);
+ }
+ $this->end_lines($filename);
+ close FILE;
+}
+
+sub iterate_fh {
+ my $this = shift;
+ my ($fh, $filename) = @_;
+
+ $this->start_lines($filename);
+ while (<$fh>) {
+ $this->next_line($_);
+ }
+ $this->end_lines($filename);
+}
+
+sub iterate_string {
+ my $this = shift;
+ my ($id, $data) = @_;
+
+ $this->start_lines($id);
+ while ($data =~ /([^\n]*(\n|$))/g) {
+ $this->next_line($1);
+ }
+ $this->end_lines($id);
+}
+
+1
diff --git a/Bugzilla/Product.pm b/Bugzilla/Product.pm
index a0079a033..452ae90fc 100644
--- a/Bugzilla/Product.pm
+++ b/Bugzilla/Product.pm
@@ -114,7 +114,7 @@ sub create {
# for each product in the list, particularly with hundreds or thousands
# of products.
sub preload {
- my ($products, $preload_flagtypes) = @_;
+ my ($products, $preload_flagtypes, $flagtypes_params) = @_;
my %prods = map { $_->id => $_ } @$products;
my @prod_ids = keys %prods;
return unless @prod_ids;
@@ -132,7 +132,7 @@ sub preload {
}
}
if ($preload_flagtypes) {
- $_->flag_types foreach @$products;
+ $_->flag_types($flagtypes_params) foreach @$products;
}
}
@@ -779,7 +779,8 @@ sub user_has_access {
}
sub flag_types {
- my $self = shift;
+ my ($self, $params) = @_;
+ $params ||= {};
return $self->{'flag_types'} if defined $self->{'flag_types'};
@@ -787,7 +788,7 @@ sub flag_types {
my $cache = Bugzilla->request_cache->{flag_types_per_product} ||= {};
$self->{flag_types} = {};
my $prod_id = $self->id;
- my $flagtypes = Bugzilla::FlagType::match({ product_id => $prod_id });
+ my $flagtypes = Bugzilla::FlagType::match({ product_id => $prod_id, %$params });
foreach my $type ('bug', 'attachment') {
my @flags = grep { $_->target_type eq $type } @$flagtypes;
@@ -816,8 +817,8 @@ sub flag_types {
sub classification {
my $self = shift;
- $self->{'classification'} ||=
- new Bugzilla::Classification($self->classification_id);
+ $self->{'classification'} ||=
+ new Bugzilla::Classification({ id => $self->classification_id, cache => 1 });
return $self->{'classification'};
}
diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm
index 656d163ea..f0cb26357 100644
--- a/Bugzilla/Search.pm
+++ b/Bugzilla/Search.pm
@@ -48,6 +48,7 @@ use Bugzilla::Group;
use Bugzilla::User;
use Bugzilla::Field;
use Bugzilla::Search::Clause;
+use Bugzilla::Search::ClauseGroup;
use Bugzilla::Search::Condition qw(condition);
use Bugzilla::Status;
use Bugzilla::Keyword;
@@ -56,9 +57,10 @@ use Data::Dumper;
use Date::Format;
use Date::Parse;
use Scalar::Util qw(blessed);
-use List::MoreUtils qw(all part uniq);
+use List::MoreUtils qw(all firstidx part uniq);
use POSIX qw(INT_MAX);
use Storable qw(dclone);
+use Time::HiRes qw(gettimeofday tv_interval);
# Description Of Boolean Charts
# -----------------------------
@@ -182,6 +184,8 @@ use constant OPERATORS => {
changedfrom => \&_changedfrom_changedto,
changedto => \&_changedfrom_changedto,
changedby => \&_changedby,
+ isempty => \&_isempty,
+ isnotempty => \&_isnotempty,
};
# Some operators are really just standard SQL operators, and are
@@ -223,6 +227,12 @@ use constant NON_NUMERIC_OPERATORS => qw(
notregexp
);
+# These operators ignore the entered value
+use constant NO_VALUE_OPERATORS => qw(
+ isempty
+ isnotempty
+);
+
use constant MULTI_SELECT_OVERRIDE => {
notequals => \&_multiselect_negative,
notregexp => \&_multiselect_negative,
@@ -292,10 +302,10 @@ use constant OPERATOR_FIELD_OVERRIDE => {
keywords => MULTI_SELECT_OVERRIDE,
'flagtypes.name' => MULTI_SELECT_OVERRIDE,
longdesc => {
- %{ MULTI_SELECT_OVERRIDE() },
changedby => \&_long_desc_changedby,
changedbefore => \&_long_desc_changedbefore_after,
changedafter => \&_long_desc_changedbefore_after,
+ _non_changed => \&_long_desc_nonchanged,
},
'longdescs.count' => {
changedby => \&_long_desc_changedby,
@@ -483,6 +493,14 @@ use constant COLUMN_JOINS => {
to => 'id',
},
},
+ blocked => {
+ table => 'dependencies',
+ to => 'dependson',
+ },
+ dependson => {
+ table => 'dependencies',
+ to => 'blocked',
+ },
'longdescs.count' => {
table => 'longdescs',
join => 'INNER',
@@ -550,6 +568,9 @@ sub COLUMNS {
. $dbh->sql_string_concat('map_flagtypes.name', 'map_flags.status')),
'keywords' => $dbh->sql_group_concat('DISTINCT map_keyworddefs.name'),
+
+ blocked => $dbh->sql_group_concat('DISTINCT map_blocked.blocked'),
+ dependson => $dbh->sql_group_concat('DISTINCT map_dependson.dependson'),
'longdescs.count' => 'COUNT(DISTINCT map_longdescs_count.comment_id)',
);
@@ -645,7 +666,9 @@ sub REPORT_COLUMNS {
# is here because it *always* goes into the GROUP BY as the first item,
# so it should be skipped when determining extra GROUP BY columns.
use constant GROUP_BY_SKIP => qw(
+ blocked
bug_id
+ dependson
flagtypes.name
keywords
longdescs.count
@@ -686,7 +709,70 @@ sub new {
# Public Accessors #
####################
-sub sql {
+sub data {
+ my $self = shift;
+ return $self->{data} if $self->{data};
+ my $dbh = Bugzilla->dbh;
+
+ # If all fields belong to the 'bugs' table, there is no need to split
+ # the original query into two pieces. Else we override the 'fields'
+ # argument to first get bug IDs based on the search criteria defined
+ # by the caller, and the desired fields are collected in the 2nd query.
+ my @orig_fields = $self->_input_columns;
+ my $all_in_bugs_table = 1;
+ foreach my $field (@orig_fields) {
+ next if $self->COLUMNS->{$field}->{name} =~ /^bugs\.\w+$/;
+ $self->{fields} = ['bug_id'];
+ $all_in_bugs_table = 0;
+ last;
+ }
+
+ my $start_time = [gettimeofday()];
+ my $sql = $self->_sql;
+ # Do we just want bug IDs to pass to the 2nd query or all the data immediately?
+ my $func = $all_in_bugs_table ? 'selectall_arrayref' : 'selectcol_arrayref';
+ my $bug_ids = $dbh->$func($sql);
+ my @extra_data = ({sql => $sql, time => tv_interval($start_time)});
+ # Restore the original 'fields' argument, just in case.
+ $self->{fields} = \@orig_fields unless $all_in_bugs_table;
+
+ # If there are no bugs found, or all fields are in the 'bugs' table,
+ # there is no need for another query.
+ if (!scalar @$bug_ids || $all_in_bugs_table) {
+ $self->{data} = $bug_ids;
+ return wantarray ? ($self->{data}, \@extra_data) : $self->{data};
+ }
+
+ # Make sure the bug_id will be returned. If not, append it to the list.
+ my $pos = firstidx { $_ eq 'bug_id' } @orig_fields;
+ if ($pos < 0) {
+ push(@orig_fields, 'bug_id');
+ $pos = $#orig_fields;
+ }
+
+ # Now create a query with the buglist above as the single criteria
+ # and the fields that the caller wants. No need to redo security checks;
+ # the list has already been validated above.
+ my $search = $self->new('fields' => \@orig_fields,
+ 'params' => {bug_id => $bug_ids, bug_id_type => 'anyexact'},
+ 'sharer' => $self->_sharer_id,
+ 'user' => $self->_user,
+ 'allow_unlimited' => 1,
+ '_no_security_check' => 1);
+
+ $start_time = [gettimeofday()];
+ $sql = $search->_sql;
+ my $unsorted_data = $dbh->selectall_arrayref($sql);
+ push(@extra_data, {sql => $sql, time => tv_interval($start_time)});
+ # Let's sort the data. We didn't do it in the query itself because
+ # we already know in which order to sort bugs thanks to the first query,
+ # and this avoids additional table joins in the SQL query.
+ my %data = map { $_->[$pos] => $_ } @$unsorted_data;
+ $self->{data} = [map { $data{$_} } @$bug_ids];
+ return wantarray ? ($self->{data}, \@extra_data) : $self->{data};
+}
+
+sub _sql {
my ($self) = @_;
return $self->{sql} if $self->{sql};
my $dbh = Bugzilla->dbh;
@@ -720,7 +806,7 @@ sub search_description {
# Make sure that the description has actually been generated if
# people are asking for the whole thing.
else {
- $self->sql;
+ $self->_sql;
}
return $self->{'search_description'};
}
@@ -1078,6 +1164,7 @@ sub _standard_joins {
my ($self) = @_;
my $user = $self->_user;
my @joins;
+ return () if $self->{_no_security_check};
my $security_join = {
table => 'bug_group_map',
@@ -1116,8 +1203,8 @@ sub _translate_join {
die "join with no table: " . Dumper($join_info) if !$join_info->{table};
die "join with no 'as': " . Dumper($join_info) if !$join_info->{as};
-
- my $from_table = "bugs";
+
+ my $from_table = $join_info->{bugs_table} || "bugs";
my $from = $join_info->{from} || "bug_id";
if ($from =~ /^(\w+)\.(\w+)$/) {
($from_table, $from) = ($1, $2);
@@ -1154,6 +1241,7 @@ sub _translate_join {
# group security.
sub _standard_where {
my ($self) = @_;
+ return ('1=1') if $self->{_no_security_check};
# If replication lags badly between the shadow db and the main DB,
# it's possible for bugs to show up in searches before their group
# controls are properly set. To prevent this, when initially creating
@@ -1522,7 +1610,7 @@ sub _charts_to_conditions {
my $clause = $self->_charts;
my @joins;
$clause->walk_conditions(sub {
- my ($condition) = @_;
+ my ($clause, $condition) = @_;
return if !$condition->translated;
push(@joins, @{ $condition->translated->{joins} });
});
@@ -1542,7 +1630,7 @@ sub _params_to_data_structure {
my ($self) = @_;
# First we get the "special" charts, representing all the normal
- # field son the search page. This may modify _params, so it needs to
+ # fields on the search page. This may modify _params, so it needs to
# happen first.
my $clause = $self->_special_charts;
@@ -1551,7 +1639,7 @@ sub _params_to_data_structure {
# And then process the modern "custom search" format.
$clause->add( $self->_custom_search );
-
+
return $clause;
}
@@ -1582,7 +1670,9 @@ sub _boolean_charts {
my $identifier = "$chart_id-$and_id-$or_id";
my $field = $params->{"field$identifier"};
my $operator = $params->{"type$identifier"};
- my $value = $params->{"value$identifier"};
+ my $value = $params->{"value$identifier"};
+ # no-value operators ignore the value, however a value needs to be set
+ $value = ' ' if $operator && grep { $_ eq $operator } NO_VALUE_OPERATORS;
$or_clause->add($field, $operator, $value);
}
$and_clause->add($or_clause);
@@ -1598,13 +1688,18 @@ sub _custom_search {
my ($self) = @_;
my $params = $self->_params;
- my $current_clause = new Bugzilla::Search::Clause($params->{j_top});
+ my $joiner = $params->{j_top} || '';
+ my $current_clause = $joiner eq 'AND_G'
+ ? new Bugzilla::Search::ClauseGroup()
+ : new Bugzilla::Search::Clause($joiner);
my @clause_stack;
foreach my $id ($self->_field_ids) {
my $field = $params->{"f$id"};
if ($field eq 'OP') {
- my $joiner = $params->{"j$id"};
- my $new_clause = new Bugzilla::Search::Clause($joiner);
+ my $joiner = $params->{"j$id"} || '';
+ my $new_clause = $joiner eq 'AND_G'
+ ? new Bugzilla::Search::ClauseGroup()
+ : new Bugzilla::Search::Clause($joiner);
$new_clause->negate($params->{"n$id"});
$current_clause->add($new_clause);
push(@clause_stack, $current_clause);
@@ -1620,6 +1715,8 @@ sub _custom_search {
my $operator = $params->{"o$id"};
my $value = $params->{"v$id"};
+ # no-value operators ignore the value, however a value needs to be set
+ $value = ' ' if $operator && grep { $_ eq $operator } NO_VALUE_OPERATORS;
my $condition = condition($field, $operator, $value);
$condition->negate($params->{"n$id"});
$current_clause->add($condition);
@@ -1643,14 +1740,12 @@ sub _field_ids {
}
sub _handle_chart {
- my ($self, $chart_id, $condition) = @_;
+ my ($self, $chart_id, $clause, $condition) = @_;
my $dbh = Bugzilla->dbh;
my $params = $self->_params;
my ($field, $operator, $value) = $condition->fov;
-
- $field = FIELD_MAP->{$field} || $field;
-
return if (!defined $field or !defined $operator or !defined $value);
+ $field = FIELD_MAP->{$field} || $field;
my $string_value;
if (ref $value eq 'ARRAY') {
@@ -1681,15 +1776,19 @@ sub _handle_chart {
# on multiple values, like anyexact.
my %search_args = (
- chart_id => $chart_id,
- sequence => $chart_id,
- field => $field,
- full_field => $full_field,
- operator => $operator,
- value => $string_value,
- all_values => $value,
- joins => [],
+ chart_id => $chart_id,
+ sequence => $chart_id,
+ field => $field,
+ full_field => $full_field,
+ operator => $operator,
+ value => $string_value,
+ all_values => $value,
+ joins => [],
+ bugs_table => 'bugs',
+ table_suffix => '',
);
+ $clause->update_search_args(\%search_args);
+
$search_args{quoted} = $self->_quote_unless_numeric(\%search_args);
# This should add a "term" selement to %search_args.
$self->do_search_function(\%search_args);
@@ -1705,7 +1804,12 @@ sub _handle_chart {
field => $field, type => $operator,
value => $string_value, term => $search_args{term},
});
-
+
+ foreach my $join (@{ $search_args{joins} }) {
+ $join->{bugs_table} = $search_args{bugs_table};
+ $join->{table_suffix} = $search_args{table_suffix};
+ }
+
$condition->translated(\%search_args);
}
@@ -1861,8 +1965,14 @@ sub _quote_unless_numeric {
}
sub build_subselect {
- my ($outer, $inner, $table, $cond) = @_;
- return "$outer IN (SELECT $inner FROM $table WHERE $cond)";
+ my ($outer, $inner, $table, $cond, $negate) = @_;
+ # Execute subselects immediately to avoid dependent subqueries, which are
+ # large performance hits on MySql
+ my $q = "SELECT DISTINCT $inner FROM $table WHERE $cond";
+ my $dbh = Bugzilla->dbh;
+ my $list = $dbh->selectcol_arrayref($q);
+ return $negate ? "1=1" : "1=2" unless @$list;
+ return $dbh->sql_in($outer, $list, $negate);
}
# Used by anyexact to get the list of input values. This allows us to
@@ -2327,6 +2437,43 @@ sub _long_desc_changedbefore_after {
}
}
+sub _long_desc_nonchanged {
+ my ($self, $args) = @_;
+ my ($chart_id, $operator, $value, $joins, $bugs_table) =
+ @$args{qw(chart_id operator value joins bugs_table)};
+ my $dbh = Bugzilla->dbh;
+
+ my $table = "longdescs_$chart_id";
+ my $join_args = {
+ chart_id => $chart_id,
+ sequence => $chart_id,
+ field => 'longdesc',
+ full_field => "$table.thetext",
+ operator => $operator,
+ value => $value,
+ all_values => $value,
+ quoted => $dbh->quote($value),
+ joins => [],
+ bugs_table => $bugs_table,
+ };
+ $self->_do_operator_function($join_args);
+
+ # If the user is not part of the insiders group, they cannot see
+ # private comments
+ if (!$self->_user->is_insider) {
+ $join_args->{term} .= " AND $table.isprivate = 0";
+ }
+
+ my $join = {
+ table => 'longdescs',
+ as => $table,
+ extra => [ $join_args->{term} ],
+ };
+ push(@$joins, $join);
+
+ $args->{term} = "$table.comment_id IS NOT NULL";
+}
+
sub _content_matches {
my ($self, $args) = @_;
my ($chart_id, $joins, $fields, $operator, $value) =
@@ -2659,8 +2806,7 @@ sub _multiselect_term {
my $term = $args->{term};
$term .= $args->{_extra_where} || '';
my $select = $args->{_select_field} || 'bug_id';
- my $not_sql = $not ? "NOT " : '';
- return "bugs.bug_id ${not_sql}IN (SELECT $select FROM $table WHERE $term)";
+ return build_subselect("$args->{bugs_table}.bug_id", $select, $table, $term, $not);
}
###############################
@@ -2879,6 +3025,27 @@ sub _changed_security_check {
}
}
+sub _isempty {
+ my ($self, $args, $join) = @_;
+ my $full_field = $args->{full_field};
+ $args->{term} = "$full_field IS NULL OR $full_field = " . $self->_empty_value($args->{field});
+}
+
+sub _isnotempty {
+ my ($self, $args, $join) = @_;
+ my $full_field = $args->{full_field};
+ $args->{term} = "$full_field IS NOT NULL AND $full_field != " . $self->_empty_value($args->{field});
+}
+
+sub _empty_value {
+ my ($self, $field) = @_;
+ return "''" unless $field =~ /^cf_/;
+ my $field_obj = $self->_chart_fields->{$field};
+ return "0" if $field_obj->type == FIELD_TYPE_BUG_ID;
+ return Bugzilla->dbh->quote(EMPTY_DATETIME) if $field_obj->type == FIELD_TYPE_DATETIME;
+ return "''";
+}
+
######################
# Public Subroutines #
######################
@@ -2887,7 +3054,8 @@ sub _changed_security_check {
sub IsValidQueryType
{
my ($queryType) = @_;
- if (grep { $_ eq $queryType } qw(specific advanced)) {
+ # BMO: Added google and instant
+ if (grep { $_ eq $queryType } qw(specific advanced google instant)) {
return 1;
}
return 0;
@@ -2927,3 +3095,109 @@ sub translate_old_column {
}
1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Search - Provides methods to run queries against bugs.
+
+=head1 SYNOPSIS
+
+ use Bugzilla::Search;
+
+ my $search = new Bugzilla::Search({'fields' => \@fields,
+ 'params' => \%search_criteria,
+ 'sharer' => $sharer_id,
+ 'user' => $user_obj,
+ 'allow_unlimited' => 1});
+
+ my $data = $search->data;
+ my ($data, $extra_data) = $search->data;
+
+=head1 DESCRIPTION
+
+Search.pm represents a search object. It's the single way to collect
+data about bugs in a secure way. The list of bugs matching criteria
+defined by the caller are filtered based on the user privileges.
+
+=head1 METHODS
+
+=head2 new
+
+=over
+
+=item B<Description>
+
+Create a Bugzilla::Search object.
+
+=item B<Params>
+
+=over
+
+=item C<fields>
+
+An arrayref representing the bug attributes for which data is desired.
+Legal attributes are listed in the fielddefs DB table. At least one field
+must be defined, typically the 'bug_id' field.
+
+=item C<params>
+
+A hashref representing search criteria. Each key => value pair represents
+a search criteria, where the key is the search field and the value is the
+value for this field. At least one search criteria must be defined if the
+'search_allow_no_criteria' parameter is turned off, else an error is thrown.
+
+=item C<sharer>
+
+When a saved search is shared by a user, this is his user ID.
+
+=item C<user>
+
+A L<Bugzilla::User> object representing the user to whom the data is addressed.
+All security checks are done based on this user object, so it's not safe
+to share results of the query with other users as not all users have the
+same privileges or have the same role for all bugs in the list. If this
+parameter is not defined, then the currently logged in user is taken into
+account. If no user is logged in, then only public bugs will be returned.
+
+=item C<allow_unlimited>
+
+If set to a true value, the number of bugs retrieved by the query is not
+limited.
+
+=back
+
+=item B<Returns>
+
+A L<Bugzilla::Search> object.
+
+=back
+
+=head2 data
+
+=over
+
+=item B<Description>
+
+Returns bugs matching search criteria passed to C<new()>.
+
+=item B<Params>
+
+None
+
+=item B<Returns>
+
+In scalar context, this method returns a reference to a list of bugs.
+Each item of the list represents a bug, which is itself a reference to
+a list where each item represents a bug attribute, in the same order as
+specified in the C<fields> parameter of C<new()>.
+
+In list context, this methods also returns a reference to a list containing
+references to hashes. For each hash, two keys are defined: C<sql> contains
+the SQL query which has been executed, and C<time> contains the time spent
+to execute the SQL query, in seconds. There can be either a single hash, or
+two hashes if two SQL queries have been executed sequentially to get all the
+required data.
+
+=back
diff --git a/Bugzilla/Search/Clause.pm b/Bugzilla/Search/Clause.pm
index a068ce5ed..38f6f30be 100644
--- a/Bugzilla/Search/Clause.pm
+++ b/Bugzilla/Search/Clause.pm
@@ -42,6 +42,11 @@ sub children {
return $self->{children};
}
+sub update_search_args {
+ my ($self, $search_args) = @_;
+ # abstract
+}
+
sub joiner { return $_[0]->{joiner} }
sub has_translated_conditions {
@@ -83,7 +88,7 @@ sub walk_conditions {
my ($self, $callback) = @_;
foreach my $child (@{ $self->children }) {
if ($child->isa('Bugzilla::Search::Condition')) {
- $callback->($child);
+ $callback->($self, $child);
}
else {
$child->walk_conditions($callback);
diff --git a/Bugzilla/Search/ClauseGroup.pm b/Bugzilla/Search/ClauseGroup.pm
new file mode 100644
index 000000000..5b437afec
--- /dev/null
+++ b/Bugzilla/Search/ClauseGroup.pm
@@ -0,0 +1,96 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Search::ClauseGroup;
+
+use strict;
+
+use base qw(Bugzilla::Search::Clause);
+
+use Bugzilla::Error;
+use Bugzilla::Search::Condition qw(condition);
+use Bugzilla::Util qw(trick_taint);
+use List::MoreUtils qw(uniq);
+
+use constant UNSUPPORTED_FIELDS => qw(
+ attach_data.thedata
+ classification
+ commenter
+ component
+ longdescs.count
+ product
+ owner_idle_time
+);
+
+sub new {
+ my ($class) = @_;
+ my $self = bless({ joiner => 'AND' }, $class);
+ # Add a join back to the bugs table which will be used to group conditions
+ # for this clause
+ my $condition = Bugzilla::Search::Condition->new({});
+ $condition->translated({
+ joins => [{
+ table => 'bugs',
+ as => 'bugs_g0',
+ from => 'bug_id',
+ to => 'bug_id',
+ extra => [],
+ }],
+ term => '1 = 1',
+ });
+ $self->SUPER::add($condition);
+ $self->{group_condition} = $condition;
+ return $self;
+}
+
+sub add {
+ my ($self, @args) = @_;
+ my $field = scalar(@args) == 3 ? $args[0] : $args[0]->{field};
+
+ # We don't support nesting of conditions under this clause
+ if (scalar(@args) == 1 && !$args[0]->isa('Bugzilla::Search::Condition')) {
+ ThrowUserError('search_grouped_invalid_nesting');
+ }
+
+ # Ensure all conditions use the same field
+ if (!$self->{_field}) {
+ $self->{_field} = $field;
+ } elsif ($field ne $self->{_field}) {
+ ThrowUserError('search_grouped_field_mismatch');
+ }
+
+ # Unsupported fields
+ if (grep { $_ eq $field } UNSUPPORTED_FIELDS ) {
+ ThrowUserError('search_grouped_field_invalid', { field => $field });
+ }
+
+ $self->SUPER::add(@args);
+}
+
+sub update_search_args {
+ my ($self, $search_args) = @_;
+
+ # No need to change things if there's only one child condition
+ return unless scalar(@{ $self->children }) > 1;
+
+ # we want all the terms to use the same join table
+ if (!exists $self->{_first_chart_id}) {
+ $self->{_first_chart_id} = $search_args->{chart_id};
+ } else {
+ $search_args->{chart_id} = $self->{_first_chart_id};
+ }
+
+ my $suffix = '_g' . $self->{_first_chart_id};
+ $self->{group_condition}->{translated}->{joins}->[0]->{as} = "bugs$suffix";
+
+ $search_args->{full_field} =~ s/^bugs\./bugs$suffix\./;
+
+ $search_args->{table_suffix} = $suffix;
+ $search_args->{bugs_table} = "bugs$suffix";
+}
+
+1;
diff --git a/Bugzilla/Search/Quicksearch.pm b/Bugzilla/Search/Quicksearch.pm
index 7424f831f..215cc842e 100644
--- a/Bugzilla/Search/Quicksearch.pm
+++ b/Bugzilla/Search/Quicksearch.pm
@@ -161,6 +161,8 @@ sub quicksearch {
ThrowUserError('quicksearch_invalid_query')
if ($words[0] =~ /^(?:AND|OR)$/ || $words[$#words] =~ /^(?:AND|OR|NOT)$/);
+ $fulltext = Bugzilla->user->setting('quicksearch_fulltext') eq 'on' ? 1 : 0;
+
my (@qswords, @or_group);
while (scalar @words) {
my $word = shift @words;
@@ -187,6 +189,10 @@ sub quicksearch {
}
unshift(@words, "-$word");
}
+ # --comment and ++comment disable or enable fulltext searching
+ elsif ($word =~ /^(--|\+\+)comments?$/i) {
+ $fulltext = $1 eq '--' ? 0 : 1;
+ }
else {
# OR groups words together, as OR has higher precedence than AND.
push(@or_group, $word);
@@ -203,7 +209,6 @@ sub quicksearch {
shift(@qswords) if $bug_status_set;
my (@unknownFields, %ambiguous_fields);
- $fulltext = Bugzilla->user->setting('quicksearch_fulltext') eq 'on' ? 1 : 0;
# Loop over all main-level QuickSearch words.
foreach my $qsword (@qswords) {
@@ -530,6 +535,9 @@ sub _default_quicksearch_word {
addChart('short_desc', 'substring', $word, $negate);
addChart('status_whiteboard', 'substring', $word, $negate);
addChart('content', 'matches', _matches_phrase($word), $negate) if $fulltext;
+
+ # BMO Bug 664124 - Include the crash signature (sig:) field in default quicksearches
+ addChart('cf_crash_signature', 'substring', $word, $negate);
}
sub _handle_urls {
diff --git a/Bugzilla/Search/Recent.pm b/Bugzilla/Search/Recent.pm
index 5f04b180b..125850e85 100644
--- a/Bugzilla/Search/Recent.pm
+++ b/Bugzilla/Search/Recent.pm
@@ -65,12 +65,13 @@ sub create {
my $user_id = $search->user_id;
# Enforce there only being SAVE_NUM_SEARCHES per user.
- my $min_id = $dbh->selectrow_array(
- 'SELECT id FROM profile_search WHERE user_id = ? ORDER BY id DESC '
- . $dbh->sql_limit(1, SAVE_NUM_SEARCHES), undef, $user_id);
- if ($min_id) {
- $dbh->do('DELETE FROM profile_search WHERE user_id = ? AND id <= ?',
- undef, ($user_id, $min_id));
+ my @ids = @{ $dbh->selectcol_arrayref(
+ "SELECT id FROM profile_search WHERE user_id = ? ORDER BY id",
+ undef, $user_id) };
+ if (scalar(@ids) > SAVE_NUM_SEARCHES) {
+ splice(@ids, - SAVE_NUM_SEARCHES);
+ $dbh->do(
+ "DELETE FROM profile_search WHERE id IN (" . join(',', @ids) . ")");
}
$dbh->bz_commit_transaction();
return $search;
diff --git a/Bugzilla/Send/Sendmail.pm b/Bugzilla/Send/Sendmail.pm
new file mode 100644
index 000000000..9513134f4
--- /dev/null
+++ b/Bugzilla/Send/Sendmail.pm
@@ -0,0 +1,95 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Send::Sendmail;
+
+use strict;
+
+use base qw(Email::Send::Sendmail);
+
+use Return::Value;
+use Symbol qw(gensym);
+
+sub send {
+ my ($class, $message, @args) = @_;
+ my $mailer = $class->_find_sendmail;
+
+ return failure "Couldn't find 'sendmail' executable in your PATH"
+ ." and Email::Send::Sendmail::SENDMAIL is not set"
+ unless $mailer;
+
+ return failure "Found $mailer but cannot execute it"
+ unless -x $mailer;
+
+ local $SIG{'CHLD'} = 'DEFAULT';
+
+ my $pipe = gensym;
+
+ open($pipe, "| $mailer -t -oi @args")
+ || return failure "Error executing $mailer: $!";
+ print($pipe $message->as_string)
+ || return failure "Error printing via pipe to $mailer: $!";
+ unless (close $pipe) {
+ return failure "error when closing pipe to $mailer: $!" if $!;
+ my ($error_message, $is_transient) = _map_exitcode($? >> 8);
+ if (Bugzilla->params->{'use_mailer_queue'}) {
+ # Return success for errors which are fatal so Bugzilla knows to
+ # remove them from the queue
+ if ($is_transient) {
+ return failure "error when closing pipe to $mailer: $error_message";
+ } else {
+ warn "error when closing pipe to $mailer: $error_message\n";
+ return success;
+ }
+ } else {
+ return failure "error when closing pipe to $mailer: $error_message";
+ }
+ }
+ return success;
+}
+
+sub _map_exitcode {
+ # Returns (error message, is_transient)
+ # from the sendmail source (sendmail/sysexit.h)
+ my $code = shift;
+ if ($code == 64) {
+ return ("Command line usage error (EX_USAGE)", 1);
+ } elsif ($code == 65) {
+ return ("Data format error (EX_DATAERR)", 1);
+ } elsif ($code == 66) {
+ return ("Cannot open input (EX_NOINPUT)", 1);
+ } elsif ($code == 67) {
+ return ("Addressee unknown (EX_NOUSER)", 0);
+ } elsif ($code == 68) {
+ return ("Host name unknown (EX_NOHOST)", 0);
+ } elsif ($code == 69) {
+ return ("Service unavailable (EX_UNAVAILABLE)", 1);
+ } elsif ($code == 70) {
+ return ("Internal software error (EX_SOFTWARE)", 1);
+ } elsif ($code == 71) {
+ return ("System error (EX_OSERR)", 1);
+ } elsif ($code == 72) {
+ return ("Critical OS file missing (EX_OSFILE)", 1);
+ } elsif ($code == 73) {
+ return ("Can't create output file (EX_CANTCREAT)", 1);
+ } elsif ($code == 74) {
+ return ("Input/output error (EX_IOERR)", 1);
+ } elsif ($code == 75) {
+ return ("Temp failure (EX_TEMPFAIL)", 1);
+ } elsif ($code == 76) {
+ return ("Remote error in protocol (EX_PROTOCOL)", 1);
+ } elsif ($code == 77) {
+ return ("Permission denied (EX_NOPERM)", 1);
+ } elsif ($code == 78) {
+ return ("Configuration error (EX_CONFIG)", 1);
+ } else {
+ return ("Unknown Error ($code)", 1);
+ }
+}
+
+1;
+
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index cd7507963..40fa0ed1e 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -236,7 +236,8 @@ sub quoteUrls {
~<a href=\"mailto:$2\">$1$2</a>~igx;
# attachment links
- $text =~ s~\b(attachment\s*\#?\s*(\d+)(?:\s+\[details\])?)
+ # BMO: Bug 652332 dkl@mozilla.com 2011-07-20
+ $text =~ s~\b(attachment\s*\#?\s*(\d+)(?:\s+\[diff\])?(?:\s+\[details\])?)
~($things[$count++] = get_attachment_link($2, $1, $user)) &&
("\0\0" . ($count-1) . "\0\0")
~egmxi;
@@ -281,7 +282,7 @@ sub get_attachment_link {
my $dbh = Bugzilla->dbh;
$user ||= Bugzilla->user;
- my $attachment = new Bugzilla::Attachment($attachid);
+ my $attachment = new Bugzilla::Attachment({ id => $attachid, cache => 1 });
if ($attachment) {
my $title = "";
@@ -298,19 +299,21 @@ sub get_attachment_link {
$title = html_quote(clean_text($title));
$link_text =~ s/ \[details\]$//;
+ $link_text =~ s/ \[diff\]$//;
my $linkval = "attachment.cgi?id=$attachid";
- # If the attachment is a patch, try to link to the diff rather
- # than the text, by default.
+ # If the attachment is a patch and patch_viewer feature is
+ # enabled, add link to the diff.
my $patchlink = "";
if ($attachment->ispatch and Bugzilla->feature('patch_viewer')) {
- $patchlink = '&amp;action=diff';
+ $patchlink = qq| <a href="${linkval}&amp;action=diff" title="$title">[diff]</a>|;
}
# Whitespace matters here because these links are in <pre> tags.
return qq|<span class="$className">|
- . qq|<a href="${linkval}${patchlink}" name="attach_${attachid}" title="$title">$link_text</a>|
+ . qq|<a href="${linkval}" name="attach_${attachid}" title="$title">$link_text</a>|
. qq| <a href="${linkval}&amp;action=edit" title="$title">[details]</a>|
+ . qq|${patchlink}|
. qq|</span>|;
}
else {
@@ -331,8 +334,8 @@ sub get_bug_link {
$options->{user} ||= Bugzilla->user;
my $dbh = Bugzilla->dbh;
- if (defined $bug) {
- $bug = blessed($bug) ? $bug : new Bugzilla::Bug($bug);
+ if (defined $bug && $bug ne '') {
+ $bug = blessed($bug) ? $bug : new Bugzilla::Bug({ id => $bug, cache => 1 });
return $link_text if $bug->{error};
}
@@ -399,13 +402,10 @@ sub mtime_filter {
#
# 1. YUI CSS
# 2. Standard Bugzilla stylesheet set (persistent)
-# 3. Standard Bugzilla stylesheet set (selectable)
-# 4. All third-party "skin" stylesheet sets (selectable)
-# 5. Page-specific styles
-# 6. Custom Bugzilla stylesheet set (persistent)
-#
-# "Selectable" skin file sets may be either preferred or alternate.
-# Exactly one is preferred, determined by the "skin" user preference.
+# 3. Third-party "skin" stylesheet set, per user prefs (persistent)
+# 4. Page-specific styles
+# 5. Custom Bugzilla stylesheet set (persistent)
+
sub css_files {
my ($style_urls, $yui, $yui_css) = @_;
@@ -422,18 +422,10 @@ sub css_files {
my @css_sets = map { _css_link_set($_) } @requested_css;
- my %by_type = (standard => [], alternate => {}, skin => [], custom => []);
+ my %by_type = (standard => [], skin => [], custom => []);
foreach my $set (@css_sets) {
foreach my $key (keys %$set) {
- if ($key eq 'alternate') {
- foreach my $alternate_skin (keys %{ $set->{alternate} }) {
- my $files = $by_type{alternate}->{$alternate_skin} ||= [];
- push(@$files, $set->{alternate}->{$alternate_skin});
- }
- }
- else {
- push(@{ $by_type{$key} }, $set->{$key});
- }
+ push(@{ $by_type{$key} }, $set->{$key});
}
}
@@ -450,27 +442,15 @@ sub _css_link_set {
if ($file_name !~ m{(^|/)skins/standard/}) {
return \%set;
}
-
- my $skin_user_prefs = Bugzilla->user->settings->{skin};
+
+ my $skin = Bugzilla->user->settings->{skin}->{value};
my $cgi_path = bz_locations()->{'cgi_path'};
- # If the DB is not accessible, user settings are not available.
- my $all_skins = $skin_user_prefs ? $skin_user_prefs->legal_values : [];
- my %skin_urls;
- foreach my $option (@$all_skins) {
- next if $option eq 'standard';
- my $skin_file_name = $file_name;
- $skin_file_name =~ s{(^|/)skins/standard/}{skins/contrib/$option/};
- if (my $mtime = _mtime("$cgi_path/$skin_file_name")) {
- $skin_urls{$option} = mtime_filter($skin_file_name, $mtime);
- }
+ my $skin_file_name = $file_name;
+ $skin_file_name =~ s{(^|/)skins/standard/}{skins/contrib/$skin/};
+ if (my $mtime = _mtime("$cgi_path/$skin_file_name")) {
+ $set{skin} = mtime_filter($skin_file_name, $mtime);
}
- $set{alternate} = \%skin_urls;
-
- my $skin = $skin_user_prefs->{'value'};
- if ($skin ne 'standard' and defined $set{alternate}->{$skin}) {
- $set{skin} = delete $set{alternate}->{$skin};
- }
-
+
my $custom_file_name = $file_name;
$custom_file_name =~ s{(^|/)skins/standard/}{skins/custom/};
if (my $custom_mtime = _mtime("$cgi_path/$custom_file_name")) {
@@ -556,10 +536,9 @@ $Template::Stash::SCALAR_OPS->{ 0 } =
$Template::Stash::SCALAR_OPS->{ truncate } =
sub {
my ($string, $length, $ellipsis) = @_;
- $ellipsis ||= "";
-
return $string if !$length || length($string) <= $length;
-
+
+ $ellipsis ||= '';
my $strlen = $length - length($ellipsis);
my $newstr = substr($string, 0, $strlen) . $ellipsis;
return $newstr;
@@ -666,6 +645,18 @@ sub create {
$var =~ s/>/\\x3e/g;
return $var;
},
+
+ # Sadly, different to the above. See http://www.json.org/
+ # for details.
+ json => sub {
+ my ($var) = @_;
+ $var =~ s/([\\\"\/])/\\$1/g;
+ $var =~ s/\n/\\n/g;
+ $var =~ s/\r/\\r/g;
+ $var =~ s/\f/\\f/g;
+ $var =~ s/\t/\\t/g;
+ return $var;
+ },
# Converts data to base64
base64 => sub {
@@ -881,14 +872,9 @@ sub create {
# Currently logged in user, if any
# If an sudo session is in progress, this is the user we're faking
'user' => sub { return Bugzilla->user; },
-
+
# Currenly active language
- # XXX Eventually this should probably be replaced with something
- # like Bugzilla->language.
- 'current_language' => sub {
- my ($language) = include_languages();
- return $language;
- },
+ 'current_language' => sub { return Bugzilla->current_language; },
# If an sudo session is in progress, this is the user who
# started the session.
@@ -899,7 +885,7 @@ sub create {
# Allow templates to access docs url with users' preferred language
'docs_urlbase' => sub {
- my ($language) = include_languages();
+ my $language = Bugzilla->current_language;
my $docs_urlbase = Bugzilla->params->{'docs_urlbase'};
$docs_urlbase =~ s/\%lang\%/$language/;
return $docs_urlbase;
@@ -928,7 +914,15 @@ sub create {
Bugzilla->fields({ by_name => 1 });
return $cache->{template_bug_fields};
},
-
+
+ # A general purpose cache to store rendered templates for reuse.
+ # Make sure to not mix language-specific data.
+ 'template_cache' => sub {
+ my $cache = Bugzilla->request_cache->{template_cache} ||= {};
+ $cache->{users} ||= {};
+ return $cache;
+ },
+
'css_files' => \&css_files,
yui_resolve_deps => \&yui_resolve_deps,
@@ -975,6 +969,12 @@ sub create {
'default_authorizer' => sub { return Bugzilla::Auth->new() },
},
};
+ # Use a per-process provider to cache compiled templates in memory across
+ # requests.
+ my $provider_key = join(':', @{ $config->{INCLUDE_PATH} });
+ my $shared_providers = Bugzilla->process_cache->{shared_providers} ||= {};
+ $shared_providers->{$provider_key} ||= Template::Provider->new($config);
+ $config->{LOAD_TEMPLATES} = [ $shared_providers->{$provider_key} ];
local $Template::Config::CONTEXT = 'Bugzilla::Template::Context';
@@ -1056,6 +1056,9 @@ sub precompile_templates {
# If anything created a Template object before now, clear it out.
delete Bugzilla->request_cache->{template};
+ # Clear out the cached Provider object
+ Bugzilla->process_cache->{shared_providers} = undef;
+
print install_string('done') . "\n" if $output;
}
diff --git a/Bugzilla/Template/Context.pm b/Bugzilla/Template/Context.pm
index 7923603e5..db1a3cf90 100644
--- a/Bugzilla/Template/Context.pm
+++ b/Bugzilla/Template/Context.pm
@@ -95,6 +95,13 @@ sub stash {
return $stash;
}
+sub filter {
+ my ($self, $name, $args) = @_;
+ # If we pass an alias for the filter name, the filter code is cached
+ # instead of looking for it at each call.
+ $self->SUPER::filter($name, $args, $name);
+}
+
# We need a DESTROY sub for the same reason that Bugzilla::CGI does.
sub DESTROY {
my $self = shift;
diff --git a/Bugzilla/Token.pm b/Bugzilla/Token.pm
index 2bb68e721..4804851bb 100644
--- a/Bugzilla/Token.pm
+++ b/Bugzilla/Token.pm
@@ -109,6 +109,8 @@ sub IssueEmailChangeToken {
$vars->{'newemailaddress'} = $new_email . $email_suffix;
$vars->{'expiration_ts'} = ctime($token_ts + MAX_TOKEN_AGE * 86400);
$vars->{'token'} = $token;
+ # For SecureMail extension
+ $vars->{'to_user'} = $user;
$vars->{'emailaddress'} = $old_email . $email_suffix;
my $message;
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index 878daea60..bd7c8123b 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -50,6 +50,7 @@ use Bugzilla::Product;
use Bugzilla::Classification;
use Bugzilla::Field;
use Bugzilla::Group;
+use Bugzilla::Hook;
use DateTime::TimeZone;
use List::Util qw(max);
@@ -431,6 +432,31 @@ sub tags {
return $self->{tags};
}
+sub bugs_ignored {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ if (!defined $self->{'bugs_ignored'}) {
+ $self->{'bugs_ignored'} = $dbh->selectall_arrayref(
+ 'SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.short_desc AS summary
+ FROM bugs
+ INNER JOIN email_bug_ignore
+ ON bugs.bug_id = email_bug_ignore.bug_id
+ WHERE user_id = ?',
+ { Slice => {} }, $self->id);
+ # Go ahead and load these into the visible bugs cache
+ # to speed up can_see_bug checks later
+ $self->visible_bugs([ map { $_->{'id'} } @{ $self->{'bugs_ignored'} } ]);
+ }
+ return $self->{'bugs_ignored'};
+}
+
+sub is_bug_ignored {
+ my ($self, $bug_id) = @_;
+ return (grep {$_->{'id'} == $bug_id} @{$self->bugs_ignored}) ? 1 : 0;
+}
+
##########################
# Saved Recent Bug Lists #
##########################
@@ -707,8 +733,8 @@ sub bless_groups {
return $self->{'bless_groups'} if defined $self->{'bless_groups'};
return [] unless $self->id;
- if ($self->in_group('editusers')) {
- # Users having editusers permissions may bless all groups.
+ if ($self->in_group('admin')) {
+ # Users having admin permissions may bless all groups.
$self->{'bless_groups'} = [Bugzilla::Group->get_all];
return $self->{'bless_groups'};
}
@@ -778,6 +804,15 @@ sub in_group_id {
return grep($_->id == $id, @{ $self->groups }) ? 1 : 0;
}
+# This is a helper to get all groups which have an icon to be displayed
+# besides the name of the commenter.
+sub groups_with_icon {
+ my $self = shift;
+
+ my @groups = grep { $_->icon_url } @{ $self->direct_group_membership };
+ return \@groups;
+}
+
sub get_products_by_permission {
my ($self, $group) = @_;
# Make sure $group exists on a per-product basis.
@@ -1635,7 +1670,9 @@ our %names_to_events = (
'attachments.mimetype' => EVT_ATTACHMENT_DATA,
'attachments.ispatch' => EVT_ATTACHMENT_DATA,
'dependson' => EVT_DEPEND_BLOCK,
- 'blocked' => EVT_DEPEND_BLOCK);
+ 'blocked' => EVT_DEPEND_BLOCK,
+ 'product' => EVT_COMPONENT,
+ 'component' => EVT_COMPONENT);
# Returns true if the user wants mail for a given bug change.
# Note: the "+" signs before the constants suppress bareword quoting.
@@ -1654,7 +1691,7 @@ sub wants_bug_mail {
}
else {
# Catch-all for any change not caught by a more specific event
- $events{+EVT_OTHER} = 1;
+ $events{+EVT_OTHER} = 1;
}
# If the user is in a particular role and the value of that role
@@ -2199,6 +2236,34 @@ groups.
Returns a hashref with tag IDs as key, and a hashref with tag 'id',
'name' and 'bug_count' as value.
+=item C<bugs_ignored>
+
+Returns an array of hashrefs containing information about bugs currently
+being ignored by the user.
+
+Each hashref contains the following information:
+
+=over
+
+=item C<id>
+
+C<int> The id of the bug.
+
+=item C<status>
+
+C<string> The current status of the bug.
+
+=item C<summary>
+
+C<string> The current summary of the bug.
+
+=back
+
+=item C<is_bug_ignored>
+
+Returns true if the user does not want email notifications for the
+specified bug ID, else returns false.
+
=back
=head2 Saved Recent Bug Lists
@@ -2363,7 +2428,7 @@ Determines whether or not a user is in the given group by id.
Returns an arrayref of L<Bugzilla::Group> objects.
The arrayref consists of the groups the user can bless, taking into account
-that having editusers permissions means that you can bless all groups, and
+that having admin permissions means that you can bless all groups, and
that you need to be able to see a group in order to bless it.
=item C<get_products_by_permission($group)>
diff --git a/Bugzilla/UserAgent.pm b/Bugzilla/UserAgent.pm
new file mode 100644
index 000000000..07b05b99c
--- /dev/null
+++ b/Bugzilla/UserAgent.pm
@@ -0,0 +1,249 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Terry Weissman <terry@mozilla.org>
+# Dave Miller <justdave@syndicomm.com>
+# Joe Robins <jmrobins@tgix.com>
+# Gervase Markham <gerv@gerv.net>
+# Shane H. W. Travis <travis@sedsystems.ca>
+# Nitish Bezzala <nbezzala@yahoo.com>
+# Byron Jones <glob@mozilla.com>
+
+package Bugzilla::UserAgent;
+
+use strict;
+use base qw(Exporter);
+our @EXPORT = qw(detect_platform detect_op_sys);
+
+use Bugzilla::Field;
+use List::MoreUtils qw(natatime);
+
+use constant DEFAULT_VALUE => 'Other';
+
+use constant PLATFORMS_MAP => (
+ # PowerPC
+ qr/\(.*PowerPC.*\)/i => ["PowerPC", "Macintosh"],
+ # AMD64, Intel x86_64
+ qr/\(.*[ix0-9]86 (?:on |\()x86_64.*\)/ => ["IA32", "x86", "PC"],
+ qr/\(.*amd64.*\)/ => ["AMD64", "x86_64", "PC"],
+ qr/\(.*x86_64.*\)/ => ["AMD64", "x86_64", "PC"],
+ # Intel IA64
+ qr/\(.*IA64.*\)/ => ["IA64", "PC"],
+ # Intel x86
+ qr/\(.*Intel.*\)/ => ["IA32", "x86", "PC"],
+ qr/\(.*[ix0-9]86.*\)/ => ["IA32", "x86", "PC"],
+ # Versions of Windows that only run on Intel x86
+ qr/\(.*Win(?:dows |)[39M].*\)/ => ["IA32", "x86", "PC"],
+ qr/\(.*Win(?:dows |)16.*\)/ => ["IA32", "x86", "PC"],
+ # Sparc
+ qr/\(.*sparc.*\)/ => ["Sparc", "Sun"],
+ qr/\(.*sun4.*\)/ => ["Sparc", "Sun"],
+ # Alpha
+ qr/\(.*AXP.*\)/i => ["Alpha", "DEC"],
+ qr/\(.*[ _]Alpha.\D/i => ["Alpha", "DEC"],
+ qr/\(.*[ _]Alpha\)/i => ["Alpha", "DEC"],
+ # MIPS
+ qr/\(.*IRIX.*\)/i => ["MIPS", "SGI"],
+ qr/\(.*MIPS.*\)/i => ["MIPS", "SGI"],
+ # 68k
+ qr/\(.*68K.*\)/ => ["68k", "Macintosh"],
+ qr/\(.*680[x0]0.*\)/ => ["68k", "Macintosh"],
+ # HP
+ qr/\(.*9000.*\)/ => ["PA-RISC", "HP"],
+ # ARM
+ qr/\(.*ARM.*\)/ => ["ARM", "PocketPC"],
+ # PocketPC intentionally before PowerPC
+ qr/\(.*Windows CE.*PPC.*\)/ => ["ARM", "PocketPC"],
+ # PowerPC
+ qr/\(.*PPC.*\)/ => ["PowerPC", "Macintosh"],
+ qr/\(.*AIX.*\)/ => ["PowerPC", "Macintosh"],
+ # Stereotypical and broken
+ qr/\(.*Windows CE.*\)/ => ["ARM", "PocketPC"],
+ qr/\(.*Macintosh.*\)/ => ["68k", "Macintosh"],
+ qr/\(.*Mac OS [89].*\)/ => ["68k", "Macintosh"],
+ qr/\(.*WOW64.*\)/ => ["x86_64"],
+ qr/\(.*Win64.*\)/ => ["IA64"],
+ qr/\(Win.*\)/ => ["IA32", "x86", "PC"],
+ qr/\(.*Win(?:dows[ -])NT.*\)/ => ["IA32", "x86", "PC"],
+ qr/\(.*OSF.*\)/ => ["Alpha", "DEC"],
+ qr/\(.*HP-?UX.*\)/i => ["PA-RISC", "HP"],
+ qr/\(.*IRIX.*\)/i => ["MIPS", "SGI"],
+ qr/\(.*(SunOS|Solaris).*\)/ => ["Sparc", "Sun"],
+ # Braindead old browsers who didn't follow convention:
+ qr/Amiga/ => ["68k", "Macintosh"],
+ qr/WinMosaic/ => ["IA32", "x86", "PC"],
+);
+
+use constant OS_MAP => (
+ # Sun
+ qr/\(.*Solaris.*\)/ => ["Solaris"],
+ qr/\(.*SunOS 5.11.*\)/ => [("OpenSolaris", "Opensolaris", "Solaris 11")],
+ qr/\(.*SunOS 5.10.*\)/ => ["Solaris 10"],
+ qr/\(.*SunOS 5.9.*\)/ => ["Solaris 9"],
+ qr/\(.*SunOS 5.8.*\)/ => ["Solaris 8"],
+ qr/\(.*SunOS 5.7.*\)/ => ["Solaris 7"],
+ qr/\(.*SunOS 5.6.*\)/ => ["Solaris 6"],
+ qr/\(.*SunOS 5.5.*\)/ => ["Solaris 5"],
+ qr/\(.*SunOS 5.*\)/ => ["Solaris"],
+ qr/\(.*SunOS.*sun4u.*\)/ => ["Solaris"],
+ qr/\(.*SunOS.*i86pc.*\)/ => ["Solaris"],
+ qr/\(.*SunOS.*\)/ => ["SunOS"],
+ # BSD
+ qr/\(.*BSD\/(?:OS|386).*\)/ => ["BSDI"],
+ qr/\(.*FreeBSD.*\)/ => ["FreeBSD"],
+ qr/\(.*OpenBSD.*\)/ => ["OpenBSD"],
+ qr/\(.*NetBSD.*\)/ => ["NetBSD"],
+ # Misc POSIX
+ qr/\(.*IRIX.*\)/ => ["IRIX"],
+ qr/\(.*OSF.*\)/ => ["OSF/1"],
+ qr/\(.*Linux.*\)/ => ["Linux"],
+ qr/\(.*BeOS.*\)/ => ["BeOS"],
+ qr/\(.*AIX.*\)/ => ["AIX"],
+ qr/\(.*OS\/2.*\)/ => ["OS/2"],
+ qr/\(.*QNX.*\)/ => ["Neutrino"],
+ qr/\(.*VMS.*\)/ => ["OpenVMS"],
+ qr/\(.*HP-?UX.*\)/ => ["HP-UX"],
+ qr/\(.*Android.*\)/ => ["Android"],
+ # Windows
+ qr/\(.*Windows XP.*\)/ => ["Windows XP"],
+ qr/\(.*Windows NT 6\.2.*\)/ => ["Windows 8"],
+ qr/\(.*Windows NT 6\.1.*\)/ => ["Windows 7"],
+ qr/\(.*Windows NT 6\.0.*\)/ => ["Windows Vista"],
+ qr/\(.*Windows NT 5\.2.*\)/ => ["Windows Server 2003"],
+ qr/\(.*Windows NT 5\.1.*\)/ => ["Windows XP"],
+ qr/\(.*Windows 2000.*\)/ => ["Windows 2000"],
+ qr/\(.*Windows NT 5.*\)/ => ["Windows 2000"],
+ qr/\(.*Win.*9[8x].*4\.9.*\)/ => ["Windows ME"],
+ qr/\(.*Win(?:dows |)M[Ee].*\)/ => ["Windows ME"],
+ qr/\(.*Win(?:dows |)98.*\)/ => ["Windows 98"],
+ qr/\(.*Win(?:dows |)95.*\)/ => ["Windows 95"],
+ qr/\(.*Win(?:dows |)16.*\)/ => ["Windows 3.1"],
+ qr/\(.*Win(?:dows[ -]|)NT.*\)/ => ["Windows NT"],
+ qr/\(.*Windows.*NT.*\)/ => ["Windows NT"],
+ # OS X
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.6.*\)/ => ["Mac OS X 10.6"],
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.5.*\)/ => ["Mac OS X 10.5"],
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.4.*\)/ => ["Mac OS X 10.4"],
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.3.*\)/ => ["Mac OS X 10.3"],
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.2.*\)/ => ["Mac OS X 10.2"],
+ qr/\(.*Mac OS X (?:|Mach-O |\()10.1.*\)/ => ["Mac OS X 10.1"],
+ # Unfortunately, OS X 10.4 was the first to support Intel. This is fallback
+ # support because some browsers refused to include the OS Version.
+ qr/\(.*Intel.*Mac OS X.*\)/ => ["Mac OS X 10.4"],
+ # OS X 10.3 is the most likely default version of PowerPC Macs
+ # OS X 10.0 is more for configurations which didn't setup 10.x versions
+ qr/\(.*Mac OS X.*\)/ => [("Mac OS X 10.3", "Mac OS X 10.0", "Mac OS X")],
+ qr/\(.*Mac OS 9.*\)/ => [("Mac System 9.x", "Mac System 9.0")],
+ qr/\(.*Mac OS 8\.6.*\)/ => [("Mac System 8.6", "Mac System 8.5")],
+ qr/\(.*Mac OS 8\.5.*\)/ => ["Mac System 8.5"],
+ qr/\(.*Mac OS 8\.1.*\)/ => [("Mac System 8.1", "Mac System 8.0")],
+ qr/\(.*Mac OS 8\.0.*\)/ => ["Mac System 8.0"],
+ qr/\(.*Mac OS 8[^.].*\)/ => ["Mac System 8.0"],
+ qr/\(.*Mac OS 8.*\)/ => ["Mac System 8.6"],
+ qr/\(.*Darwin.*\)/ => [("Mac OS X 10.0", "Mac OS X")],
+ # Silly
+ qr/\(.*Mac.*PowerPC.*\)/ => ["Mac System 9.x"],
+ qr/\(.*Mac.*PPC.*\)/ => ["Mac System 9.x"],
+ qr/\(.*Mac.*68k.*\)/ => ["Mac System 8.0"],
+ # Evil
+ qr/Amiga/i => ["Other"],
+ qr/WinMosaic/ => ["Windows 95"],
+ qr/\(.*32bit.*\)/ => ["Windows 95"],
+ qr/\(.*16bit.*\)/ => ["Windows 3.1"],
+ qr/\(.*PowerPC.*\)/ => ["Mac System 9.x"],
+ qr/\(.*PPC.*\)/ => ["Mac System 9.x"],
+ qr/\(.*68K.*\)/ => ["Mac System 8.0"],
+);
+
+sub detect_platform {
+ my $userAgent = $ENV{'HTTP_USER_AGENT'} || '';
+ my @detected;
+ my $iterator = natatime(2, PLATFORMS_MAP);
+ while (my($re, $ra) = $iterator->()) {
+ if ($userAgent =~ $re) {
+ push @detected, @$ra;
+ }
+ }
+ return _pick_valid_field_value('rep_platform', @detected);
+}
+
+sub detect_op_sys {
+ my $userAgent = $ENV{'HTTP_USER_AGENT'} || '';
+ my @detected;
+ my $iterator = natatime(2, OS_MAP);
+ while (my($re, $ra) = $iterator->()) {
+ if ($userAgent =~ $re) {
+ push @detected, @$ra;
+ }
+ }
+ push(@detected, "Windows") if grep(/^Windows /, @detected);
+ push(@detected, "Mac OS") if grep(/^Mac /, @detected);
+ return _pick_valid_field_value('op_sys', @detected);
+}
+
+# Takes the name of a field and a list of possible values for that field.
+# Returns the first value in the list that is actually a valid value for that
+# field.
+# Returns 'Other' if none of the values match.
+sub _pick_valid_field_value {
+ my ($field, @values) = @_;
+ foreach my $value (@values) {
+ return $value if check_field($field, $value, undef, 1);
+ }
+ return DEFAULT_VALUE;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::UserAgent - UserAgent utilities for Bugzilla
+
+=head1 SYNOPSIS
+
+ use Bugzilla::UserAgent;
+ printf "platform: %s op-sys: %s\n", detect_platform(), detect_op_sys();
+
+=head1 DESCRIPTION
+
+The functions exported by this module all return information derived from the
+remote client's user agent.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<detect_platform>
+
+This function attempts to detect the remote client's platform from the
+presented user-agent. If a suitable value on the I<platform> field is found,
+that field value will be returned. If no suitable value is detected,
+C<detect_platform> returns I<Other>.
+
+=item C<detect_op_sys>
+
+This function attempts to detect the remote client's operating system from the
+presented user-agent. If a suitable value on the I<op_sys> field is found, that
+field value will be returned. If no suitable value is detected,
+C<detect_op_sys> returns I<Other>.
+
+=back
+
diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm
index c2dbdc97d..e8d1438f3 100644
--- a/Bugzilla/Util.pm
+++ b/Bugzilla/Util.pm
@@ -44,7 +44,7 @@ use base qw(Exporter);
bz_crypt generate_random_password
validate_email_syntax clean_text
get_text template_var disable_utf8
- detect_encoding);
+ detect_encoding email_filter);
use Bugzilla::Constants;
use Bugzilla::RNG qw(irand);
@@ -57,7 +57,6 @@ use Digest;
use Email::Address;
use List::Util qw(first);
use Scalar::Util qw(tainted blessed);
-use Template::Filters;
use Text::Wrap;
use Encode qw(encode decode resolve_alias);
use Encode::Guess;
@@ -87,7 +86,11 @@ sub detaint_signed {
# visible strings.
# Bug 319331: Handle BiDi disruptions.
sub html_quote {
- my ($var) = Template::Filters::html_filter(@_);
+ my $var = shift;
+ $var =~ s/&/&amp;/g;
+ $var =~ s/</&lt;/g;
+ $var =~ s/>/&gt;/g;
+ $var =~ s/"/&quot;/g;
# Obscure '@'.
$var =~ s/\@/\&#64;/g;
if (Bugzilla->params->{'utf8'}) {
@@ -119,6 +122,9 @@ sub html_quote {
sub html_light_quote {
my ($text) = @_;
+ # admin/table.html.tmpl calls |FILTER html_light| many times.
+ # There is no need to recreate the HTML::Scrubber object again and again.
+ my $scrubber = Bugzilla->process_cache->{html_scrubber};
# List of allowed HTML elements having no attributes.
my @allow = qw(b strong em i u p br abbr acronym ins del cite code var
@@ -140,7 +146,7 @@ sub html_light_quote {
$text =~ s#$chr($safe)$chr#<$1>#go;
return $text;
}
- else {
+ elsif (!$scrubber) {
# We can be less restrictive. We can accept elements with attributes.
push(@allow, qw(a blockquote q span));
@@ -183,14 +189,14 @@ sub html_light_quote {
},
);
- my $scrubber = HTML::Scrubber->new(default => \@default,
- allow => \@allow,
- rules => \@rules,
- comment => 0,
- process => 0);
-
- return $scrubber->scrub($text);
+ Bugzilla->process_cache->{html_scrubber} = $scrubber =
+ HTML::Scrubber->new(default => \@default,
+ allow => \@allow,
+ rules => \@rules,
+ comment => 0,
+ process => 0);
}
+ return $scrubber->scrub($text);
}
sub email_filter {
@@ -726,10 +732,12 @@ sub get_text {
sub template_var {
my $name = shift;
- my $cache = Bugzilla->request_cache->{util_template_var} ||= {};
- my $template = Bugzilla->template_inner;
- my $lang = $template->context->{bz_language};
+ my $request_cache = Bugzilla->request_cache;
+ my $cache = $request_cache->{util_template_var} ||= {};
+ my $lang = $request_cache->{template_current_lang}->[0];
return $cache->{$lang}->{$name} if defined $cache->{$lang};
+
+ my $template = Bugzilla->template_inner($lang);
my %vars;
# Note: If we suddenly start needing a lot of template_var variables,
# they should move into their own template, not field-descs.
@@ -746,11 +754,7 @@ sub template_var {
sub display_value {
my ($field, $value) = @_;
- my $value_descs = template_var('value_descs');
- if (defined $value_descs->{$field}->{$value}) {
- return $value_descs->{$field}->{$value};
- }
- return $value;
+ return template_var('value_descs')->{$field}->{$value} // $value;
}
sub disable_utf8 {
diff --git a/Bugzilla/WebService.pm b/Bugzilla/WebService.pm
index 166707626..55df8124d 100644
--- a/Bugzilla/WebService.pm
+++ b/Bugzilla/WebService.pm
@@ -79,6 +79,11 @@ A floating-point number. May be null.
A string. May be null.
+=item C<email>
+
+A string representing an email address. This value, when returned,
+may be filtered based on if the user is logged in or not. May be null.
+
=item C<dateTime>
A date/time. Represented differently in different interfaces to this API.
@@ -277,6 +282,13 @@ the returned hashes.
If you specify all the fields, then this function will return empty
hashes.
+Some RPC calls support specifying sub fields. If an RPC call states that
+it support sub field restrictions, you can restrict what information is
+returned within the first field. For example, if you call Products.get
+with an include_fields of components.name, then only the component name
+would be returned (and nothing else). You can include the main field,
+and exclude a sub field.
+
Invalid field names are ignored.
Specifying fields here overrides C<include_fields>, so if you specify a
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm
index 578c06ec5..b6cfe897b 100644
--- a/Bugzilla/WebService/Bug.pm
+++ b/Bugzilla/WebService/Bug.pm
@@ -82,6 +82,8 @@ BEGIN {
sub fields {
my ($self, $params) = validate(@_, 'ids', 'names');
+ Bugzilla->switch_to_shadow_db();
+
my @fields;
if (defined $params->{ids}) {
my $ids = $params->{ids};
@@ -117,11 +119,12 @@ sub fields {
my (@values, $has_values);
if ( ($field->is_select and $field->name ne 'product')
- or grep($_ eq $field->name, PRODUCT_SPECIFIC_FIELDS))
+ or grep($_ eq $field->name, PRODUCT_SPECIFIC_FIELDS)
+ or $field->name eq 'keywords')
{
$has_values = 1;
@values = @{ $self->_legal_field_values({ field => $field }) };
- }
+ }
if (grep($_ eq $field->name, PRODUCT_SPECIFIC_FIELDS)) {
$value_field = 'product';
@@ -211,6 +214,15 @@ sub _legal_field_values {
}
}
+ elsif ($field_name eq 'keywords') {
+ my @legal_keywords = Bugzilla::Keyword->get_all;
+ foreach my $value (@legal_keywords) {
+ push (@result, {
+ name => $self->type('string', $value->name),
+ description => $self->type('string', $value->description),
+ });
+ }
+ }
else {
my @values = Bugzilla::Field::Choice->type($field)->get_all();
foreach my $value (@values) {
@@ -242,7 +254,7 @@ sub comments {
my $bug_ids = $params->{ids} || [];
my $comment_ids = $params->{comment_ids} || [];
- my $dbh = Bugzilla->dbh;
+ my $dbh = Bugzilla->switch_to_shadow_db();
my $user = Bugzilla->user;
my %bugs;
@@ -297,9 +309,10 @@ sub _translate_comment {
return filter $filters, {
id => $self->type('int', $comment->id),
bug_id => $self->type('int', $comment->bug_id),
- creator => $self->type('string', $comment->author->login),
- author => $self->type('string', $comment->author->login),
+ creator => $self->type('email', $comment->author->login),
+ author => $self->type('email', $comment->author->login),
time => $self->type('dateTime', $comment->creation_ts),
+ creation_time => $self->type('dateTime', $comment->creation_ts),
is_private => $self->type('boolean', $comment->is_private),
text => $self->type('string', $comment->body_full),
attachment_id => $self->type('int', $attach_id),
@@ -309,8 +322,11 @@ sub _translate_comment {
sub get {
my ($self, $params) = validate(@_, 'ids');
+ Bugzilla->switch_to_shadow_db();
+
my $ids = $params->{ids};
- defined $ids || ThrowCodeError('param_required', { param => 'ids' });
+ (defined $ids && scalar @$ids)
+ || ThrowCodeError('param_required', { param => 'ids' });
my @bugs;
my @faults;
@@ -343,34 +359,39 @@ sub get {
sub history {
my ($self, $params) = validate(@_, 'ids');
+ Bugzilla->switch_to_shadow_db();
+
my $ids = $params->{ids};
defined $ids || ThrowCodeError('param_required', { param => 'ids' });
- my @return;
+ my %api_name = reverse %{ Bugzilla::Bug::FIELD_MAP() };
+ $api_name{'bug_group'} = 'groups';
+ my @return;
foreach my $bug_id (@$ids) {
my %item;
my $bug = Bugzilla::Bug->check($bug_id);
$bug_id = $bug->id;
$item{id} = $self->type('int', $bug_id);
- my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id);
+ my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id, undef, $params->{start_time});
my @history;
foreach my $changeset (@$activity) {
my %bug_history;
$bug_history{when} = $self->type('dateTime', $changeset->{when});
- $bug_history{who} = $self->type('string', $changeset->{who});
+ $bug_history{who} = $self->type('email', $changeset->{who});
$bug_history{changes} = [];
foreach my $change (@{ $changeset->{changes} }) {
+ my $api_field = $api_name{$change->{fieldname}} || $change->{fieldname};
my $attach_id = delete $change->{attachid};
if ($attach_id) {
$change->{attachment_id} = $self->type('int', $attach_id);
}
$change->{removed} = $self->type('string', $change->{removed});
$change->{added} = $self->type('string', $change->{added});
- $change->{field_name} = $self->type('string',
- delete $change->{fieldname});
+ $change->{field_name} = $self->type('string', $api_field);
+ delete $change->{fieldname};
push (@{$bug_history{changes}}, $change);
}
@@ -399,7 +420,9 @@ sub history {
sub search {
my ($self, $params) = @_;
-
+
+ Bugzilla->switch_to_shadow_db();
+
if ( defined($params->{offset}) and !defined($params->{limit}) ) {
ThrowCodeError('param_required',
{ param => 'limit', function => 'Bug.search()' });
@@ -439,16 +462,25 @@ sub search {
delete $match_params{'include_fields'};
delete $match_params{'exclude_fields'};
+ my $count_only = delete $match_params{count_only};
+
my $bugs = Bugzilla::Bug->match(\%match_params);
my $visible = Bugzilla->user->visible_bugs($bugs);
- my @hashes = map { $self->_bug_to_hash($_, $params) } @$visible;
- return { bugs => \@hashes };
+ if ($count_only) {
+ return { bug_count => scalar @$visible };
+ }
+ else {
+ my @hashes = map { $self->_bug_to_hash($_, $params) } @$visible;
+ return { bugs => \@hashes };
+ }
}
sub possible_duplicates {
my ($self, $params) = validate(@_, 'product');
my $user = Bugzilla->user;
+ Bugzilla->switch_to_shadow_db();
+
# Undo the array-ification that validate() does, for "summary".
$params->{summary} || ThrowCodeError('param_required',
{ function => 'Bug.possible_duplicates', param => 'summary' });
@@ -469,6 +501,12 @@ sub possible_duplicates {
sub update {
my ($self, $params) = validate(@_, 'ids');
+ # BMO: Don't allow updating of bugs if disabled
+ if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+ }
+
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $dbh = Bugzilla->dbh;
@@ -563,6 +601,13 @@ sub update {
sub create {
my ($self, $params) = @_;
+
+ # BMO: Don't allow updating of bugs if disabled
+ if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+ }
+
Bugzilla->login(LOGIN_REQUIRED);
$params = Bugzilla::Bug::map_fields($params);
my $bug = Bugzilla::Bug->create($params);
@@ -573,6 +618,8 @@ sub create {
sub legal_values {
my ($self, $params) = @_;
+ Bugzilla->switch_to_shadow_db();
+
defined $params->{field}
or ThrowCodeError('param_required', { param => 'field' });
@@ -625,6 +672,12 @@ sub add_attachment {
my ($self, $params) = validate(@_, 'ids');
my $dbh = Bugzilla->dbh;
+ # BMO: Don't allow updating of bugs if disabled
+ if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+ }
+
Bugzilla->login(LOGIN_REQUIRED);
defined $params->{ids}
|| ThrowCodeError('param_required', { param => 'ids' });
@@ -673,6 +726,12 @@ sub add_attachment {
sub add_comment {
my ($self, $params) = @_;
+ # BMO: Don't allow updating of bugs if disabled
+ if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+ }
+
#The user must login in order add a comment
Bugzilla->login(LOGIN_REQUIRED);
@@ -717,6 +776,12 @@ sub add_comment {
sub update_see_also {
my ($self, $params) = @_;
+ # BMO: Don't allow updating of bugs if disabled
+ if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+ }
+
my $user = Bugzilla->login(LOGIN_REQUIRED);
# Check parameters
@@ -764,6 +829,8 @@ sub update_see_also {
sub attachments {
my ($self, $params) = validate(@_, 'ids', 'attachment_ids');
+ Bugzilla->switch_to_shadow_db();
+
if (!(defined $params->{ids}
or defined $params->{attachment_ids}))
{
@@ -842,18 +909,18 @@ sub _bug_to_hash {
# We don't do the SQL calls at all if the filter would just
# eliminate them anyway.
if (filter_wants $params, 'assigned_to') {
- $item{'assigned_to'} = $self->type('string', $bug->assigned_to->login);
+ $item{'assigned_to'} = $self->type('email', $bug->assigned_to->login);
}
if (filter_wants $params, 'blocks') {
my @blocks = map { $self->type('int', $_) } @{ $bug->blocked };
$item{'blocks'} = \@blocks;
}
if (filter_wants $params, 'cc') {
- my @cc = map { $self->type('string', $_) } @{ $bug->cc || [] };
+ my @cc = map { $self->type('email', $_) } @{ $bug->cc || [] };
$item{'cc'} = \@cc;
}
if (filter_wants $params, 'creator') {
- $item{'creator'} = $self->type('string', $bug->reporter->login);
+ $item{'creator'} = $self->type('email', $bug->reporter->login);
}
if (filter_wants $params, 'depends_on') {
my @depends_on = map { $self->type('int', $_) } @{ $bug->dependson };
@@ -877,13 +944,16 @@ sub _bug_to_hash {
}
if (filter_wants $params, 'qa_contact') {
my $qa_login = $bug->qa_contact ? $bug->qa_contact->login : '';
- $item{'qa_contact'} = $self->type('string', $qa_login);
+ $item{'qa_contact'} = $self->type('email', $qa_login);
}
if (filter_wants $params, 'see_also') {
my @see_also = map { $self->type('string', $_->name) }
@{ $bug->see_also };
$item{'see_also'} = \@see_also;
}
+ if (filter_wants $params, 'flags') {
+ $item{'flags'} = [ map { $self->_flag_to_hash($_) } @{$bug->flags} ];
+ }
# And now custom fields
my @custom_fields = Bugzilla->active_custom_fields;
@@ -912,6 +982,7 @@ sub _bug_to_hash {
# No need to format $bug->deadline specially, because Bugzilla::Bug
# already does it for us.
$item{'deadline'} = $self->type('string', $bug->deadline);
+ $item{'actual_time'} = $self->type('double', $bug->actual_time);
}
if (Bugzilla->user->id) {
@@ -932,9 +1003,6 @@ sub _bug_to_hash {
sub _attachment_to_hash {
my ($self, $attach, $filters) = @_;
- # Skipping attachment flags for now.
- delete $attach->{flags};
-
my $item = filter $filters, {
creation_time => $self->type('dateTime', $attach->attached),
last_change_time => $self->type('dateTime', $attach->modification_time),
@@ -953,7 +1021,7 @@ sub _attachment_to_hash {
# the filter wants them.
foreach my $field (qw(creator attacher)) {
if (filter_wants $filters, $field) {
- $item->{$field} = $self->type('string', $attach->attacher->login);
+ $item->{$field} = $self->type('email', $attach->attacher->login);
}
}
@@ -961,6 +1029,31 @@ sub _attachment_to_hash {
$item->{'data'} = $self->type('base64', $attach->data);
}
+ if (filter_wants $filters, 'flags') {
+ $item->{'flags'} = [ map { $self->_flag_to_hash($_) } @{$attach->flags} ];
+ }
+
+ return $item;
+}
+
+sub _flag_to_hash {
+ my ($self, $flag) = @_;
+
+ my $item = {
+ id => $self->type('int', $flag->id),
+ name => $self->type('string', $flag->name),
+ type_id => $self->type('int', $flag->type_id),
+ creation_date => $self->type('dateTime', $flag->creation_date),
+ modification_date => $self->type('dateTime', $flag->modification_date),
+ status => $self->type('string', $flag->status)
+ };
+
+ foreach my $field (qw(setter requestee)) {
+ my $field_id = $field . "_id";
+ $item->{$field} = $self->type('email', $flag->$field->login)
+ if $flag->$field_id;
+ }
+
return $item;
}
@@ -1099,7 +1192,7 @@ values of the field are shown in the user interface. Can be null.
This is an array of hashes, representing the legal values for
select-type (drop-down and multiple-selection) fields. This is also
-populated for the C<component>, C<version>, and C<target_milestone>
+populated for the C<component>, C<version>, C<target_milestone>, and C<keywords>
fields, but not for the C<product> field (you must use
L<Product.get_accessible_products|Bugzilla::WebService::Product/get_accessible_products>
for that.
@@ -1132,6 +1225,11 @@ if the C<value_field> is set to one of the values listed in this array.
Note that for per-product fields, C<value_field> is set to C<'product'>
and C<visibility_values> will reflect which product(s) this value appears in.
+=item C<description>
+
+C<string> The description of the value. This item is only included for the
+C<keywords> field.
+
=item C<is_open>
C<boolean> For C<bug_status> values, determines whether this status
@@ -1361,6 +1459,48 @@ Also returned as C<attacher>, for backwards-compatibility with older
Bugzillas. (However, this backwards-compatibility will go away in Bugzilla
5.0.)
+=item C<flags>
+
+An array of hashes containing the information about flags currently set
+for each attachment. Each flag hash contains the following items:
+
+=over
+
+=item C<id>
+
+C<int> The id of the flag.
+
+=item C<name>
+
+C<string> The name of the flag.
+
+=item C<type_id>
+
+C<int> The type id of the flag.
+
+=item C<creation_date>
+
+C<dateTime> The timestamp when this flag was originally created.
+
+=item C<modification_date>
+
+C<dateTime> The timestamp when the flag was last modified.
+
+=item C<status>
+
+C<string> The current status of the flag.
+
+=item C<setter>
+
+C<string> The login name of the user who created or last modified the flag.
+
+=item C<requestee>
+
+C<string> The login name of the user this flag has been requested to be granted or denied.
+Note, this field is only returned if a requestee is set.
+
+=back
+
=back
=item B<Errors>
@@ -1397,6 +1537,8 @@ C<summary>.
=back
+=item The C<flags> array was added in Bugzilla B<4.4>.
+
=back
@@ -1501,6 +1643,13 @@ Bugzillas. (However, this backwards-compatibility will go away in Bugzilla
C<dateTime> The time (in Bugzilla's timezone) that the comment was added.
+=item creation_time
+
+C<dateTime> This is exactly same as the C<time> key. Use this field instead of
+C<time> for consistency with other methods including L</get> and L</attachments>.
+For compatibility, C<time> is still usable. However, please note that C<time>
+may be deprecated and removed in a future release.
+
=item is_private
C<boolean> True if this comment is private (only visible to a certain
@@ -1542,6 +1691,8 @@ C<creator>.
=back
+=item C<creation_time> was added in Bugzilla B<4.4>.
+
=back
@@ -1601,6 +1752,13 @@ the valid ids. Each hash contains the following items:
=over
+=item C<actual_time>
+
+C<double> The total number of hours that this bug has taken (so far).
+
+If you are not in the time-tracking group, this field will not be included
+in the return value.
+
=item C<alias>
C<string> The unique alias of this bug.
@@ -1659,6 +1817,48 @@ take.
If you are not in the time-tracking group, this field will not be included
in the return value.
+=item C<flags>
+
+An array of hashes containing the information about flags currently set
+for the bug. Each flag hash contains the following items:
+
+=over
+
+=item C<id>
+
+C<int> The id of the flag.
+
+=item C<name>
+
+C<string> The name of the flag.
+
+=item C<type_id>
+
+C<int> The type id of the flag.
+
+=item C<creation_date>
+
+C<dateTime> The timestamp when this flag was originally created.
+
+=item C<modification_date>
+
+C<dateTime> The timestamp when the flag was last modified.
+
+=item C<status>
+
+C<string> The current status of the flag.
+
+=item C<setter>
+
+C<string> The login name of the user who created or last modified the flag.
+
+=item C<requestee>
+
+C<string> The login name of the user this flag has been requested to be granted or denied.
+Note, this field is only returned if a requestee is set.
+
+=back
+
=item C<groups>
C<array> of C<string>s. The names of all the groups that this bug is in.
@@ -1886,8 +2086,12 @@ C<op_sys>, C<platform>, C<qa_contact>, C<remaining_time>, C<see_also>,
C<target_milestone>, C<update_token>, C<url>, C<version>, C<whiteboard>,
and all custom fields.
-=back
+=item The C<flags> array was added in Bugzilla B<4.4>.
+
+=item The C<actual_time> item was added to the C<bugs> return value
+in Bugzilla B<4.4>.
+=back
=back
@@ -1918,6 +2122,11 @@ Note that it's possible for aliases to be disabled in Bugzilla, in which
case you will be told that you have specified an invalid bug_id if you
try to specify an alias. (It will be error 100.)
+=item C<start_time>
+
+An optional C<datetime> string that only shows changes at and after a specific
+time.
+
=back
=item B<Returns>
@@ -1993,6 +2202,10 @@ The same as L</get>.
=item Added in Bugzilla B<3.4>.
+=item Field names changed to be more consistent with other methods in Bugzilla B<4.4>.
+
+=item As of Bugzilla B<4.4>, field names now match names used by L<Bug.update|/"update"> for consistency.
+
=back
=back
@@ -2153,6 +2366,11 @@ C<string> Search the "Status Whiteboard" field on bugs for a substring.
Works the same as the C<summary> field described above, but searches the
Status Whiteboard field.
+=item C<count_only>
+
+C<boolean> If count_only set to true, only a single hash key called C<bug_count>
+will be returned which is the number of bugs that matched the search.
+
=back
=item B<Returns>
diff --git a/Bugzilla/WebService/Product.pm b/Bugzilla/WebService/Product.pm
index 3cd0d0a6c..525339cda 100644
--- a/Bugzilla/WebService/Product.pm
+++ b/Bugzilla/WebService/Product.pm
@@ -47,23 +47,28 @@ BEGIN { *get_products = \&get }
# Get the ids of the products the user can search
sub get_selectable_products {
+ Bugzilla->switch_to_shadow_db();
return {ids => [map {$_->id} @{Bugzilla->user->get_selectable_products}]};
}
# Get the ids of the products the user can enter bugs against
sub get_enterable_products {
+ Bugzilla->switch_to_shadow_db();
return {ids => [map {$_->id} @{Bugzilla->user->get_enterable_products}]};
}
# Get the union of the products the user can search and enter bugs against.
sub get_accessible_products {
+ Bugzilla->switch_to_shadow_db();
return {ids => [map {$_->id} @{Bugzilla->user->get_accessible_products}]};
}
# Get a list of actual products, based on list of ids or names
sub get {
my ($self, $params) = validate(@_, 'ids', 'names');
-
+
+ Bugzilla->switch_to_shadow_db();
+
# Only products that are in the users accessible products,
# can be allowed to be returned
my $accessible_products = Bugzilla->user->get_accessible_products;
@@ -148,40 +153,41 @@ sub _product_to_hash {
}
if (filter_wants($params, 'versions')) {
$field_data->{versions} = [map {
- $self->_version_to_hash($_)
+ $self->_version_to_hash($_, $params)
} @{$product->versions}];
}
if (filter_wants($params, 'milestones')) {
$field_data->{milestones} = [map {
- $self->_milestone_to_hash($_)
+ $self->_milestone_to_hash($_, $params)
} @{$product->milestones}];
}
return filter($params, $field_data);
}
sub _component_to_hash {
- my ($self, $component) = @_;
- return {
+ my ($self, $component, $params) = @_;
+ my $field_data = {
id =>
$self->type('int', $component->id),
name =>
$self->type('string', $component->name),
description =>
- $self->type('string' , $component->description),
+ $self->type('string', $component->description),
default_assigned_to =>
- $self->type('string' , $component->default_assignee->login),
+ $self->type('email', $component->default_assignee->login),
default_qa_contact =>
- $self->type('string' , $component->default_qa_contact->login),
+ $self->type('email', $component->default_qa_contact->login),
sort_key => # sort_key is returned to match Bug.fields
0,
is_active =>
$self->type('boolean', $component->is_active),
};
+ return filter($params, $field_data, 'components');
}
sub _version_to_hash {
- my ($self, $version) = @_;
- return {
+ my ($self, $version, $params) = @_;
+ my $field_data = {
id =>
$self->type('int', $version->id),
name =>
@@ -191,11 +197,12 @@ sub _version_to_hash {
is_active =>
$self->type('boolean', $version->is_active),
};
+ return filter($params, $field_data, 'versions');
}
sub _milestone_to_hash {
- my ($self, $milestone) = @_;
- return {
+ my ($self, $milestone, $params) = @_;
+ my $field_data = {
id =>
$self->type('int', $milestone->id),
name =>
@@ -205,6 +212,7 @@ sub _milestone_to_hash {
is_active =>
$self->type('boolean', $milestone->is_active),
};
+ return filter($params, $field_data, 'milestones');
}
1;
@@ -310,6 +318,8 @@ In addition to the parameters below, this method also accepts the
standard L<include_fields|Bugzilla::WebService/include_fields> and
L<exclude_fields|Bugzilla::WebService/exclude_fields> arguments.
+This RPC call supports sub field restrictions.
+
=over
=item C<ids>
diff --git a/Bugzilla/WebService/Server/JSONRPC.pm b/Bugzilla/WebService/Server/JSONRPC.pm
index cec1c29ea..63e9ca335 100644
--- a/Bugzilla/WebService/Server/JSONRPC.pm
+++ b/Bugzilla/WebService/Server/JSONRPC.pm
@@ -38,7 +38,7 @@ BEGIN {
use Bugzilla::Error;
use Bugzilla::WebService::Constants;
use Bugzilla::WebService::Util qw(taint_data);
-use Bugzilla::Util qw(correct_urlbase trim disable_utf8);
+use Bugzilla::Util;
use HTTP::Message;
use MIME::Base64 qw(decode_base64 encode_base64);
@@ -221,6 +221,9 @@ sub type {
utf8::encode($value) if utf8::is_utf8($value);
$retval = encode_base64($value, '');
}
+ elsif ($type eq 'email' && Bugzilla->params->{'webservice_email_filter'}) {
+ $retval = email_filter($value);
+ }
return $retval;
}
diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm
index 025fb8f19..824f6ee2d 100644
--- a/Bugzilla/WebService/Server/XMLRPC.pm
+++ b/Bugzilla/WebService/Server/XMLRPC.pm
@@ -30,6 +30,7 @@ if ($ENV{MOD_PERL}) {
}
use Bugzilla::WebService::Constants;
+use Bugzilla::Util;
# Allow WebService methods to call XMLRPC::Lite's type method directly
BEGIN {
@@ -41,6 +42,12 @@ BEGIN {
$value = Bugzilla::WebService::Server->datetime_format_outbound($value);
$value =~ s/-//g;
}
+ elsif ($type eq 'email') {
+ $type = 'string';
+ if (Bugzilla->params->{'webservice_email_filter'}) {
+ $value = email_filter($value);
+ }
+ }
return XMLRPC::Data->type($type)->value($value);
};
}
diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm
index deb7518ec..758c69aa8 100644
--- a/Bugzilla/WebService/User.pm
+++ b/Bugzilla/WebService/User.pm
@@ -29,6 +29,7 @@ use Bugzilla::Group;
use Bugzilla::User;
use Bugzilla::Util qw(trim);
use Bugzilla::WebService::Util qw(filter validate);
+use Bugzilla::Hook;
# Don't need auth to login
use constant LOGIN_EXEMPT => {
@@ -126,6 +127,8 @@ sub create {
sub get {
my ($self, $params) = validate(@_, 'names', 'ids');
+ Bugzilla->switch_to_shadow_db();
+
defined($params->{names}) || defined($params->{ids})
|| defined($params->{match})
|| ThrowCodeError('params_required',
@@ -154,8 +157,8 @@ sub get {
\@user_objects, $params);
@users = map {filter $params, {
id => $self->type('int', $_->id),
- real_name => $self->type('string', $_->name),
- name => $self->type('string', $_->login),
+ real_name => $self->type('string', $_->name),
+ name => $self->type('email', $_->login),
}} @$in_group;
return { users => \@users };
@@ -196,33 +199,39 @@ sub get {
}
}
}
-
+
my $in_group = $self->_filter_users_by_group(
\@user_objects, $params);
if (Bugzilla->user->in_group('editusers')) {
- @users =
+ @users =
map {filter $params, {
id => $self->type('int', $_->id),
real_name => $self->type('string', $_->name),
- name => $self->type('string', $_->login),
- email => $self->type('string', $_->email),
+ name => $self->type('email', $_->login),
+ email => $self->type('email', $_->email),
can_login => $self->type('boolean', $_->is_enabled ? 1 : 0),
+ groups => $self->_filter_bless_groups($_->groups),
email_enabled => $self->type('boolean', $_->email_enabled),
login_denied_text => $self->type('string', $_->disabledtext),
+ saved_searches => [map { $self->_query_to_hash($_) } @{ $_->queries }],
}} @$in_group;
-
}
else {
@users =
map {filter $params, {
id => $self->type('int', $_->id),
real_name => $self->type('string', $_->name),
- name => $self->type('string', $_->login),
- email => $self->type('string', $_->email),
+ name => $self->type('email', $_->login),
+ email => $self->type('email', $_->email),
can_login => $self->type('boolean', $_->is_enabled ? 1 : 0),
+ groups => $self->_filter_bless_groups($_->groups),
+ saved_searches => [map { $self->_query_to_hash($_) } @{ $_->queries }],
}} @$in_group;
}
+ Bugzilla::Hook::process('webservice_user_get',
+ { webservice => $self, params => $params, users => \@users });
+
return { users => \@users };
}
@@ -259,6 +268,40 @@ sub _user_in_any_group {
return 0;
}
+sub _filter_bless_groups {
+ my ($self, $groups) = @_;
+ my $user = Bugzilla->user;
+
+ my @filtered_groups;
+ foreach my $group (@$groups) {
+ next unless ($user->in_group('editusers') || $user->can_bless($group->id));
+ push(@filtered_groups, $self->_group_to_hash($group));
+ }
+
+ return \@filtered_groups;
+}
+
+sub _group_to_hash {
+ my ($self, $group) = @_;
+ my $item = {
+ id => $self->type('int', $group->id),
+ name => $self->type('string', $group->name),
+ description => $self->type('string', $group->description),
+ };
+ return $item;
+}
+
+sub _query_to_hash {
+ my ($self, $query) = @_;
+ my $item = {
+ id => $self->type('int', $query->id),
+ name => $self->type('string', $query->name),
+ url => $self->type('string', $query->url),
+ };
+
+ return $item;
+}
+
1;
__END__
@@ -581,10 +624,60 @@ C<string> A text field that holds the reason for disabling a user from logging
into bugzilla, if empty then the user account is enabled. Otherwise it is
disabled/closed.
+=item groups
+
+C<array> An array of group hashes the user is a member of. Each hash describes
+the group and contains the following items:
+
+=over
+
+=item id
+
+C<int> The group id
+
+=item name
+
+C<string> The name of the group
+
+=item description
+
+C<string> The description for the group
+
+=back
+
+=over
+
+=item saved_searches
+
+C<array> An array of hashes, each of which represents a user's saved search and has
+the following keys:
+
+=over
+
+=item id
+
+C<int> An integer id uniquely identifying the saved search.
+
+=item name
+
+C<string> The name of the saved search.
+
+=item url
+
+C<string> The CGI parameters for the saved search.
+
+=back
+
+B<Note>: The elements of the returned array (i.e. hashes) are ordered by the
+name of each saved search.
+
+=back
+
B<Note>: If you are not logged in to Bugzilla when you call this function, you
will only be returned the C<id>, C<name>, and C<real_name> items. If you are
logged in and not in editusers group, you will only be returned the C<id>, C<name>,
-C<real_name>, C<email>, and C<can_login> items.
+C<real_name>, C<email>, and C<can_login> items. The groups returned are filtered
+based on your permission to bless each group.
=back
@@ -625,6 +718,10 @@ exist or you do not belong to it.
=item C<include_disabled> added in Bugzilla B<4.0>. Default behavior
for C<match> has changed to only returning enabled accounts.
+=item C<groups> Added in Bugzilla B<4.4>.
+
+=item C<saved_searches> Added in Bugzilla B<4.4>.
+
=item Error 804 has been added in Bugzilla 4.0.9 and 4.2.4. It's now
illegal to pass a group name you don't belong to.
diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm
index fe4105ca2..193dab92d 100644
--- a/Bugzilla/WebService/Util.pm
+++ b/Bugzilla/WebService/Util.pm
@@ -34,27 +34,38 @@ our @EXPORT_OK = qw(
validate
);
-sub filter ($$) {
- my ($params, $hash) = @_;
+sub filter ($$;$) {
+ my ($params, $hash, $prefix) = @_;
my %newhash = %$hash;
foreach my $key (keys %$hash) {
- delete $newhash{$key} if !filter_wants($params, $key);
+ delete $newhash{$key} if !filter_wants($params, $key, $prefix);
}
return \%newhash;
}
-sub filter_wants ($$) {
- my ($params, $field) = @_;
+sub filter_wants ($$;$) {
+ my ($params, $field, $prefix) = @_;
my %include = map { $_ => 1 } @{ $params->{'include_fields'} || [] };
my %exclude = map { $_ => 1 } @{ $params->{'exclude_fields'} || [] };
- if (defined $params->{include_fields}) {
- return 0 if !$include{$field};
+ $field = "${prefix}.${field}" if $prefix;
+
+ if (defined $params->{exclude_fields} && $exclude{$field}) {
+ return 0;
}
- if (defined $params->{exclude_fields}) {
- return 0 if $exclude{$field};
+ if (defined $params->{include_fields} && !$include{$field}) {
+ if ($prefix) {
+ # Include the field if the parent is include (and this one is not excluded)
+ return 0 if !$include{$prefix};
+ }
+ else {
+ # We want to include this if one of the sub keys is included
+ my $key = $field . '.';
+ my $len = length($key);
+ return 0 if ! grep { substr($_, 0, $len) eq $key } keys %include;
+ }
}
return 1;
@@ -136,6 +147,13 @@ of WebService methods. Given a hash (the second argument to this subroutine),
this will remove any keys that are I<not> in C<include_fields> and then remove
any keys that I<are> in C<exclude_fields>.
+An optional third option can be passed that prefixes the field name to allow
+filtering of data two or more levels deep.
+
+For example, if you want to filter out the C<id> key/value in components returned
+by Product.get, you would use the value C<component.id> in your C<exclude_fields>
+list.
+
=head2 filter_wants
Returns C<1> if a filter would preserve the specified field when passing
diff --git a/arecibo.pl b/arecibo.pl
new file mode 100755
index 000000000..93c34c999
--- /dev/null
+++ b/arecibo.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl -w
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+#
+# report errors to arecibo
+# expects a filename with a Data::Dumper serialised parameters
+# called by Bugzilla::Arecibo
+#
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib $Bin;
+use lib "$Bin/lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use File::Slurp;
+use POSIX qw(setsid nice);
+use Safe;
+use Fcntl qw(:flock);
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+nice(19);
+
+# detach
+open(STDIN, '</dev/null');
+open(STDOUT, '>/dev/null');
+open(STDERR, '>/dev/null');
+setsid();
+
+# grab arecibo server url
+my $arecibo_server = Bugzilla->params->{arecibo_server} || '';
+exit(1) unless $arecibo_server;
+
+# read data dump
+exit(1) unless my $filename = shift;
+my $dump = read_file($filename);
+unlink($filename);
+
+# deserialise
+my $cpt = new Safe;
+$cpt->reval($dump) || exit(1);
+my $data = ${$cpt->varglob('VAR1')};
+
+# ensure we send warnings one at a time per webhead
+flock(DATA, LOCK_EX);
+
+# and post to arecibo
+my $agent = LWP::UserAgent->new(
+ agent => 'bugzilla.mozilla.org',
+ timeout => 10, # seconds
+);
+$agent->post($arecibo_server, $data);
+
+__DATA__
+this exists so the flock() code works.
+do not remove this data section.
diff --git a/attachment.cgi b/attachment.cgi
index 64f78dc36..b5c0f8efe 100755
--- a/attachment.cgi
+++ b/attachment.cgi
@@ -76,6 +76,12 @@ local our $vars = {};
my $action = $cgi->param('action') || 'view';
my $format = $cgi->param('format') || '';
+# BMO: Don't allow updating of bugs if disabled
+if (Bugzilla->params->{disable_bug_updates} && $cgi->request_method eq 'POST') {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+}
+
# You must use the appropriate urlbase/sslbase param when doing anything
# but viewing an attachment, or a raw diff.
if ($action ne 'view'
@@ -174,7 +180,7 @@ sub validateID {
{ attach_id => scalar $cgi->param($param) });
# Make sure the attachment exists in the database.
- my $attachment = new Bugzilla::Attachment($attach_id)
+ my $attachment = new Bugzilla::Attachment({ id => $attach_id, cache => 1 })
|| ThrowUserError("invalid_attach_id", { attach_id => $attach_id });
return $attachment if ($dont_validate_access || check_can_access($attachment));
@@ -186,7 +192,7 @@ sub check_can_access {
my $user = Bugzilla->user;
# Make sure the user is authorized to access this attachment's bug.
- Bugzilla::Bug->check($attachment->bug_id);
+ Bugzilla::Bug->check({ id => $attachment->bug_id, cache => 1 });
if ($attachment->isprivate && $user->id != $attachment->attacher->id
&& !$user->is_insider)
{
@@ -448,7 +454,7 @@ sub diff {
# HTML page.
sub viewall {
# Retrieve and validate parameters
- my $bug = Bugzilla::Bug->check(scalar $cgi->param('bugid'));
+ my $bug = Bugzilla::Bug->check({ id => scalar $cgi->param('bugid'), cache => 1 });
my $bugid = $bug->id;
my $attachments = Bugzilla::Attachment->get_attachments_by_bug($bugid);
@@ -496,7 +502,8 @@ sub enter {
my $flag_types = Bugzilla::FlagType::match({'target_type' => 'attachment',
'product_id' => $bug->product_id,
- 'component_id' => $bug->component_id});
+ 'component_id' => $bug->component_id,
+ 'is_active' => 1});
$vars->{'flag_types'} = $flag_types;
$vars->{'any_flags_requesteeble'} =
grep { $_->is_requestable && $_->is_requesteeble } @$flag_types;
@@ -617,8 +624,6 @@ sub edit {
my $bugattachments =
Bugzilla::Attachment->get_attachments_by_bug($attachment->bug_id);
- # We only want attachment IDs.
- @$bugattachments = map { $_->id } @$bugattachments;
my $any_flags_requesteeble =
grep { $_->is_requestable && $_->is_requesteeble } @{$attachment->flag_types};
@@ -774,7 +779,6 @@ sub delete_attachment {
# The token is valid. Delete the content of the attachment.
my $msg;
$vars->{'attachment'} = $attachment;
- $vars->{'date'} = $date;
$vars->{'reason'} = clean_text($cgi->param('reason') || '');
$template->process("attachment/delete_reason.txt.tmpl", $vars, \$msg)
diff --git a/buglist.cgi b/buglist.cgi
index b5604d2bd..2d81ed56d 100755
--- a/buglist.cgi
+++ b/buglist.cgi
@@ -775,8 +775,6 @@ my $search = new Bugzilla::Search('fields' => \@selectcolumns,
'params' => scalar $params->Vars,
'order' => \@orderstrings,
'sharer' => $sharer_id);
-my $query = $search->sql;
-$vars->{'search_description'} = $search->search_description;
# We don't want saved searches and other buglist things to save
# our default limit.
@@ -786,21 +784,6 @@ $params->delete('limit') if $vars->{'default_limited'};
# Query Execution
################################################################################
-if ($cgi->param('debug')
- && Bugzilla->params->{debug_group}
- && $user->in_group(Bugzilla->params->{debug_group})
-) {
- $vars->{'debug'} = 1;
- $vars->{'query'} = $query;
- # Explains are limited to admins because you could use them to figure
- # out how many hidden bugs are in a particular product (by doing
- # searches and looking at the number of rows the explain says it's
- # examining).
- if (Bugzilla->user->in_group('admin')) {
- $vars->{'query_explain'} = $dbh->bz_explain($query);
- }
-}
-
# Time to use server push to display an interim message to the user until
# the query completes and we can display the bug list.
if ($serverpush) {
@@ -833,9 +816,28 @@ $::SIG{TERM} = 'DEFAULT';
$::SIG{PIPE} = 'DEFAULT';
# Execute the query.
-my $buglist_sth = $dbh->prepare($query);
-$buglist_sth->execute();
+my ($data, $extra_data) = $search->data;
+$vars->{'search_description'} = $search->search_description;
+if ($cgi->param('debug')
+ && Bugzilla->params->{debug_group}
+ && $user->in_group(Bugzilla->params->{debug_group})
+) {
+ $vars->{'debug'} = 1;
+ $vars->{'queries'} = $extra_data;
+ my $query_time = 0;
+ $query_time += $_->{'time'} foreach @$extra_data;
+ $vars->{'query_time'} = $query_time;
+ # Explains are limited to admins because you could use them to figure
+ # out how many hidden bugs are in a particular product (by doing
+ # searches and looking at the number of rows the explain says it's
+ # examining).
+ if ($user->in_group('admin')) {
+ foreach my $query (@$extra_data) {
+ $query->{explain} = $dbh->bz_explain($query->{sql});
+ }
+ }
+}
################################################################################
# Results Retrieval
@@ -867,14 +869,14 @@ my @bugidlist;
my @bugs; # the list of records
-while (my @row = $buglist_sth->fetchrow_array()) {
+foreach my $row (@$data) {
my $bug = {}; # a record
# Slurp the row of data into the record.
# The second from last column in the record is the number of groups
# to which the bug is restricted.
foreach my $column (@selectcolumns) {
- $bug->{$column} = shift @row;
+ $bug->{$column} = shift @$row;
}
# Process certain values further (i.e. date format conversion).
diff --git a/bzr-update.sh b/bzr-update.sh
new file mode 100644
index 000000000..e1d88e5d7
--- /dev/null
+++ b/bzr-update.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+HOST=`hostname -s`
+TAG="current-staging"
+[ "$HOST" == "mradm02" -o "$HOST" == "ip-admin02" ] && TAG="current-production"
+echo "+ bzr pull --overwrite -rtag:$TAG"
+output=`bzr pull --overwrite -rtag:$TAG 2>&1`
+echo "$output"
+echo "$output" | grep "Now on revision" | sed -e 's/Now on revision //' -e 's/\.$//' | xargs -i{} echo bzr pull --overwrite -r{} \# `date` >> `dirname $0`/cvs-update.log
+contrib/fixperms.pl
diff --git a/chart.cgi b/chart.cgi
index e7a0f5e8b..89fefbc3f 100755
--- a/chart.cgi
+++ b/chart.cgi
@@ -274,7 +274,8 @@ sub assertCanCreate {
# Check permission for frequency
my $min_freq = 7;
- if ($cgi->param('frequency') < $min_freq && !$user->in_group("admin")) {
+ # Upstreaming: denied, as this min_freq feature is going away.
+ if ($cgi->param('frequency') < $min_freq && !$user->in_group("bz_canusewhines")) {
ThrowUserError("illegal_frequency", { 'minimum' => $min_freq });
}
}
diff --git a/collectstats.pl b/collectstats.pl
index 1487e5a72..c5db30b5f 100755
--- a/collectstats.pl
+++ b/collectstats.pl
@@ -504,8 +504,7 @@ sub CollectSeriesData {
'fields' => ["bug_id"],
'allow_unlimited' => 1,
'user' => $user);
- my $sql = $search->sql;
- $data = $shadow_dbh->selectall_arrayref($sql);
+ $data = $search->data;
};
if (!$@) {
diff --git a/config.cgi b/config.cgi
index 2c82fdc59..963224638 100755
--- a/config.cgi
+++ b/config.cgi
@@ -82,7 +82,7 @@ if ($cgi->param('product')) {
}
# We set the 2nd argument to 1 to also preload flag types.
-Bugzilla::Product::preload($vars->{'products'}, 1);
+Bugzilla::Product::preload($vars->{'products'}, 1, { is_active => 1 });
# Allow consumers to specify whether or not they want flag data.
if (defined $cgi->param('flags')) {
diff --git a/contrib/addcustomfield.pl b/contrib/addcustomfield.pl
new file mode 100755
index 000000000..c7f93c297
--- /dev/null
+++ b/contrib/addcustomfield.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
+# David Miller <justdave@mozilla.com>
+
+use strict;
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Field;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my %types = (
+ 'freetext' => FIELD_TYPE_FREETEXT,
+ 'single_select' => FIELD_TYPE_SINGLE_SELECT,
+ 'multi_select' => FIELD_TYPE_MULTI_SELECT,
+ 'textarea' => FIELD_TYPE_TEXTAREA,
+ 'datetime' => FIELD_TYPE_DATETIME,
+ 'bug_id' => FIELD_TYPE_BUG_ID,
+ 'bug_urls' => FIELD_TYPE_BUG_URLS,
+ 'keywords' => FIELD_TYPE_KEYWORDS,
+);
+
+my $syntax =
+ "syntax: addcustomfield.pl <field name> [field type]\n\n" .
+ "valid field types:\n " . join("\n ", sort keys %types) . "\n\n" .
+ "the default field type is single_select\n";
+
+my $name = shift || die $syntax;
+my $type = lc(shift || 'single_select');
+exists $types{$type} || die "Invalid field type '$type'.\n\n$syntax";
+$type = $types{$type};
+
+Bugzilla::Field->create({
+ name => $name,
+ description => 'Please give me a description!',
+ type => $type,
+ mailhead => 0,
+ enter_bug => 0,
+ obsolete => 1,
+ custom => 1,
+ buglist => 1,
+});
+print "Done!\n";
+
+my $urlbase = Bugzilla->params->{urlbase};
+print "Please visit ${urlbase}editfields.cgi?action=edit&name=$name to finish setting up this field.\n";
diff --git a/contrib/fix_comment_text.pl b/contrib/fix_comment_text.pl
new file mode 100755
index 000000000..f17bbc3d4
--- /dev/null
+++ b/contrib/fix_comment_text.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+# FILE: fix_comment_text.pl
+#
+# USAGE: ./fix_comment_text.pl <comment_id>
+#
+# DESCRIPTION: Updates a comment in Bugzilla with the text after __DATA__
+#
+# OPTIONS: <comment_id> - The comment id from longdescs with the comment
+# to be replaced.
+# REQUIREMENTS: ---
+# BUGS: ---
+# NOTES: ---
+# AUTHOR: David Lawrence (:dkl), dkl@mozilla.com
+# COMPANY: Mozilla Foundation
+# VERSION: 1.0
+# CREATED: 06/20/2011 03:40:22 PM
+# REVISION: ---
+#===============================================================================
+
+use strict;
+use warnings;
+
+use lib ".";
+
+use Bugzilla;
+use Bugzilla::Util qw(detaint_natural);
+
+my $comment_id = shift;
+
+if (!detaint_natural($comment_id)) {
+ print "Error: invalid comment id or comment id not provided.\n" .
+ "Usage: ./fix_comment_text.pl <comment_id>\n";
+ exit(1);
+}
+
+my $dbh = Bugzilla->dbh;
+
+my $comment = join("", <DATA>);
+
+if ($comment =~ /ENTER NEW COMMENT TEXT HERE/) {
+ print "Please enter the new comment text in the script " .
+ "after the __DATA__ marker.\n";
+ exit(1);
+}
+
+$dbh->bz_start_transaction;
+
+Bugzilla->dbh->do(
+ "UPDATE longdescs SET thetext = ? WHERE comment_id = ?",
+ undef, $comment, $comment_id);
+
+$dbh->bz_commit_transaction;
+
+exit(0);
+
+__DATA__
+ENTER NEW COMMENT TEXT HERE BELOW THE __DATA__ MARKER!
diff --git a/contrib/moco-ldap-check.pl b/contrib/moco-ldap-check.pl
new file mode 100755
index 000000000..7a3a6ca8c
--- /dev/null
+++ b/contrib/moco-ldap-check.pl
@@ -0,0 +1,542 @@
+#!/usr/bin/perl
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin/..";
+use lib "$Bin/../lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Group;
+use Bugzilla::Mailer;
+use Data::Dumper;
+use File::Slurp;
+use Getopt::Long;
+use Net::LDAP;
+use Safe;
+
+#
+
+use constant BUGZILLA_IGNORE => <<'EOF';
+ infra+bot@mozilla.com # Mozilla Infrastructure Bot
+ qa-auto@mozilla.com # QA Desktop Automation
+ qualys@mozilla.com # Qualys Security Scanner
+ recruiting@mozilla.com # Recruiting
+ release@mozilla.com # Mozilla RelEng Bot
+ sumo-dev@mozilla.com # SUMOdev [:sumodev]
+ airmozilla@mozilla.com # Air Mozilla
+ ux-review@mozilla.com
+ release-mgmt@mozilla.com
+ reps@mozilla.com
+ moz_bug_r_a4@mozilla.com # Security contractor
+ nightwatch@mozilla.com # Security distribution list for whines
+EOF
+
+use constant LDAP_IGNORE => <<'EOF';
+ airmozilla@mozilla.com # Air Mozilla
+EOF
+
+# REPORT_SENDER has to be a valid @mozilla.com LDAP account
+use constant REPORT_SENDER => 'bjones@mozilla.com';
+
+use constant BMO_RECIPIENTS => qw(
+ glob@mozilla.com
+ dkl@mozilla.com
+);
+
+use constant SUPPORT_RECIPIENTS => qw(
+ desktop@mozilla.com
+);
+
+#
+
+my ($ldap_host, $ldap_user, $ldap_pass, $debug, $no_update);
+GetOptions('h=s' => \$ldap_host,
+ 'u=s' => \$ldap_user,
+ 'p=s' => \$ldap_pass,
+ 'd' => \$debug,
+ 'n' => \$no_update);
+die "syntax: -h ldap_host -u ldap_user -p ldap_pass\n"
+ unless $ldap_host && $ldap_user && $ldap_pass;
+
+my $data_dir = bz_locations()->{'datadir'} . '/moco-ldap-check';
+mkdir($data_dir) unless -d $data_dir;
+
+if ($ldap_user !~ /,/) {
+ $ldap_user = "mail=$ldap_user,o=com,dc=mozilla";
+}
+
+#
+# group members
+#
+
+my @bugzilla_ignore;
+foreach my $line (split(/\n/, BUGZILLA_IGNORE)) {
+ $line =~ s/^([^#]+)#.*$/$1/;
+ $line =~ s/(^\s+|\s+$)//g;
+ push @bugzilla_ignore, clean_email($line);
+}
+
+my @bugzilla_moco;
+if ($no_update && -s "$data_dir/bugzilla_moco.last") {
+ $debug && print "Using cached user list from Bugzilla...\n";
+ my $ra = deserialise("$data_dir/bugzilla_moco.last");
+ @bugzilla_moco = @$ra;
+} else {
+ $debug && print "Getting user list from Bugzilla...\n";
+
+ my $group = Bugzilla::Group->new({ name => 'mozilla-corporation' })
+ or die "Failed to find group mozilla-corporation\n";
+
+ foreach my $user (@{ $group->members_non_inherited }) {
+ next unless $user->is_enabled;
+ my $mail = clean_email($user->login);
+ my $name = trim($user->name);
+ $name =~ s/\s+/ /g;
+ next if grep { $mail eq $_ } @bugzilla_ignore;
+ push @bugzilla_moco, {
+ mail => $user->login,
+ canon => $mail,
+ name => $name,
+ };
+ }
+
+ @bugzilla_moco = sort { $a->{mail} cmp $b->{mail} } @bugzilla_moco;
+ serialise("$data_dir/bugzilla_moco.last", \@bugzilla_moco);
+}
+
+#
+# build list of current mo-co bugmail accounts
+#
+
+my @ldap_ignore;
+foreach my $line (split(/\n/, LDAP_IGNORE)) {
+ $line =~ s/^([^#]+)#.*$/$1/;
+ $line =~ s/(^\s+|\s+$)//g;
+ push @ldap_ignore, canon_email($line);
+}
+
+my %ldap;
+if ($no_update && -s "$data_dir/ldap.last") {
+ $debug && print "Using cached user list from LDAP...\n";
+ my $rh = deserialise("$data_dir/ldap.last");
+ %ldap = %$rh;
+} else {
+ $debug && print "Logging into LDAP as $ldap_user...\n";
+ my $ldap = Net::LDAP->new($ldap_host,
+ scheme => 'ldaps', onerror => 'die') or die "$@";
+ $ldap->bind($ldap_user, password => $ldap_pass);
+ foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') {
+ $debug && print "Getting user list from LDAP $ldap_base...\n";
+ my $result = $ldap->search(
+ base => $ldap_base,
+ scope => 'sub',
+ filter => '(mail=*)',
+ attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'],
+ );
+ foreach my $entry ($result->entries) {
+ my ($name, $bugMail, $mail, $type) =
+ map { $entry->get_value($_) || '' }
+ qw(cn bugzillaEmail mail employeeType);
+ next if $type eq 'DISABLED';
+ $mail = lc $mail;
+ next if grep { $_ eq canon_email($mail) } @ldap_ignore;
+ $bugMail = '' if $bugMail !~ /\@/;
+ $bugMail =~ s/(^\s+|\s+$)//g;
+ if ($bugMail =~ / /) {
+ $bugMail = (grep { /\@/ } split / /, $bugMail)[0];
+ }
+ $name =~ s/\s+/ /g;
+ $ldap{$mail}{name} = trim($name);
+ $ldap{$mail}{bugmail} = $bugMail;
+ $ldap{$mail}{bugmail_canon} = canon_email($bugMail);
+ $ldap{$mail}{aliases} = [];
+ foreach my $alias (
+ @{$entry->get_value('emailAlias', asref => 1) || []}
+ ) {
+ push @{$ldap{$mail}{aliases}}, canon_email($alias);
+ }
+ }
+ $debug && printf "Found %s entries\n", scalar($result->entries);
+ }
+ serialise("$data_dir/ldap.last", \%ldap);
+}
+
+#
+# validate all bugmail entries from the phonebook
+#
+
+my %bugzilla_login;
+if ($no_update && -s "$data_dir/bugzilla_login.last") {
+ $debug && print "Using cached bugzilla checks...\n";
+ my $rh = deserialise("$data_dir/bugzilla_login.last");
+ %bugzilla_login = %$rh;
+} else {
+ my %logins;
+ foreach my $mail (keys %ldap) {
+ $logins{$mail} = 1;
+ $logins{$ldap{$mail}{bugmail}} = 1 if $ldap{$mail}{bugmail};
+ }
+ my @logins = sort keys %logins;
+ $debug && print "Checking " . scalar(@logins) . " bugmail accounts...\n";
+
+ foreach my $login (@logins) {
+ if (Bugzilla::User->new({ name => $login })) {
+ $bugzilla_login{$login} = 1;
+ }
+ }
+ serialise("$data_dir/bugzilla_login.last", \%bugzilla_login);
+}
+
+#
+# load previous ldap list
+#
+
+my %ldap_old;
+{
+ my $rh = deserialise("$data_dir/ldap.data");
+ %ldap_old = %$rh if $rh;
+}
+
+#
+# save current ldap list
+#
+
+{
+ serialise("$data_dir/ldap.data", \%ldap);
+}
+
+#
+# new ldap accounts
+#
+
+my @new_ldap;
+{
+ foreach my $mail (sort keys %ldap) {
+ next if exists $ldap_old{$mail};
+ push @new_ldap, {
+ mail => $mail,
+ name => $ldap{$mail}{name},
+ bugmail => $ldap{$mail}{bugmail},
+ };
+ }
+}
+
+#
+# deleted ldap accounts
+#
+
+my @gone_ldap_bmo;
+my @gone_ldap_no_bmo;
+{
+ foreach my $mail (sort keys %ldap_old) {
+ next if exists $ldap{$mail};
+ if ($ldap_old{$mail}{bugmail}) {
+ push @gone_ldap_bmo, {
+ mail => $mail,
+ name => $ldap_old{$mail}{name},
+ bugmail => $ldap_old{$mail}{bugmail},
+ }
+ } else {
+ push @gone_ldap_no_bmo, {
+ mail => $mail,
+ name => $ldap_old{$mail}{name},
+ }
+ }
+ }
+}
+
+#
+# check bugmail entry for all users in bmo/moco group
+#
+
+my @suspect_bugzilla;
+my @invalid_bugzilla;
+foreach my $rh (@bugzilla_moco) {
+ my @check = ($rh->{mail}, $rh->{canon});
+ if ($rh->{mail} =~ /^([^\@]+)\@mozilla\.org$/) {
+ push @check, "$1\@mozilla.com";
+ }
+
+ my $exists;
+ foreach my $check (@check) {
+ $exists = 0;
+
+ # don't complain about deleted accounts
+ if (grep { $_->{mail} eq $check } (@gone_ldap_bmo, @gone_ldap_no_bmo)) {
+ $exists = 1;
+ last;
+ }
+
+ # check for matching bugmail entry
+ foreach my $mail (sort keys %ldap) {
+ next unless $ldap{$mail}{bugmail_canon} eq $check;
+ $exists = 1;
+ last;
+ }
+ last if $exists;
+
+ # check for matching mail
+ $exists = 0;
+ foreach my $mail (sort keys %ldap) {
+ next unless $mail eq $check;
+ $exists = 1;
+ last;
+ }
+ last if $exists;
+
+ # check for matching email alias
+ $exists = 0;
+ foreach my $mail (sort keys %ldap) {
+ next unless grep { $check eq $_ } @{$ldap{$mail}{aliases}};
+ $exists = 1;
+ last;
+ }
+ last if $exists;
+ }
+
+ if (!$exists) {
+ # flag the account
+ if ($rh->{mail} =~ /\@mozilla\.(com|org)$/i) {
+ push @invalid_bugzilla, {
+ mail => $rh->{mail},
+ name => $rh->{name},
+ };
+ } else {
+ push @suspect_bugzilla, {
+ mail => $rh->{mail},
+ name => $rh->{name},
+ };
+ }
+ }
+}
+
+#
+# check bugmail entry for ldap users
+#
+
+my @ldap_unblessed;
+my @invalid_ldap;
+my @invalid_bugmail;
+foreach my $mail (sort keys %ldap) {
+ # try to find the bmo account
+ my $found;
+ foreach my $address ($ldap{$mail}{bugmail}, $ldap{$mail}{bugmail_canon}, $mail, @{$ldap{$mail}{aliases}}) {
+ if (exists $bugzilla_login{$address}) {
+ $found = $address;
+ last;
+ }
+ }
+
+ # not on bmo
+ if (!$found) {
+ # if they have specified a bugmail account, warn, otherwise ignore
+ if ($ldap{$mail}{bugmail}) {
+ if (grep { $_->{canon} eq $ldap{$mail}{bugmail_canon} } @bugzilla_moco) {
+ push @invalid_bugmail, {
+ mail => $mail,
+ name => $ldap{$mail}{name},
+ bugmail => $ldap{$mail}{bugmail},
+ };
+ } else {
+ push @invalid_ldap, {
+ mail => $mail,
+ name => $ldap{$mail}{name},
+ bugmail => $ldap{$mail}{bugmail},
+ };
+ }
+ }
+ next;
+ }
+
+ # warn about mismatches
+ if ($ldap{$mail}{bugmail} && $found ne $ldap{$mail}{bugmail}) {
+ push @invalid_bugmail, {
+ mail => $mail,
+ name => $ldap{$mail}{name},
+ bugmail => $ldap{$mail}{bugmail},
+ };
+ }
+
+ # warn about unblessed accounts
+ if ($mail =~ /\@mozilla\.com$/) {
+ unless (grep { $_->{mail} eq $found || $_->{canon} eq canon_email($found) } @bugzilla_moco) {
+ push @ldap_unblessed, {
+ mail => $mail,
+ name => $ldap{$mail}{name},
+ bugmail => $ldap{$mail}{bugmail} || $mail,
+ };
+ }
+ }
+}
+
+#
+# reports
+#
+
+my @bmo_report;
+push @bmo_report, generate_report(
+ 'new ldap accounts',
+ 'no action required',
+ @new_ldap);
+
+push @bmo_report, generate_report(
+ 'deleted ldap accounts',
+ 'disable bmo account',
+ @gone_ldap_bmo);
+
+push @bmo_report, generate_report(
+ 'deleted ldap accounts',
+ 'no action required (no bmo account)',
+ @gone_ldap_no_bmo);
+
+push @bmo_report, generate_report(
+ 'suspect bugzilla accounts',
+ 'remove from mo-co if required',
+ @suspect_bugzilla);
+
+push @bmo_report, generate_report(
+ 'miss-configured bugzilla accounts',
+ 'ask owner to update phonebook, disable if not on phonebook',
+ @invalid_bugzilla);
+
+push @bmo_report, generate_report(
+ 'ldap accounts without mo-co group',
+ 'verify, and add mo-co group to bmo account',
+ @ldap_unblessed);
+
+push @bmo_report, generate_report(
+ 'missmatched bugmail entries on ldap accounts',
+ 'ask owner to update phonebook',
+ @invalid_bugmail);
+
+push @bmo_report, generate_report(
+ 'invalid bugmail entries on ldap accounts',
+ 'ask owner to update phonebook',
+ @invalid_ldap);
+
+if (!scalar @bmo_report) {
+ push @bmo_report, '**';
+ push @bmo_report, '** nothing to report \o/';
+ push @bmo_report, '**';
+}
+
+email_report(\@bmo_report, 'moco-ldap-check', BMO_RECIPIENTS);
+
+my @support_report;
+
+push @support_report, generate_report(
+ 'Missmatched "Bugzilla Email" entries on LDAP accounts',
+ 'Ask owner to update phonebook, or update directly',
+ @invalid_bugmail);
+
+push @support_report, generate_report(
+ 'Invalid "Bugzilla Email" entries on LDAP accounts',
+ 'Ask owner to update phonebook',
+ @invalid_ldap);
+
+if (scalar @support_report) {
+ email_report(\@support_report, 'Invalid "Bugzilla Email" entries in LDAP', SUPPORT_RECIPIENTS);
+}
+
+#
+#
+#
+
+sub generate_report {
+ my ($title, $action, @lines) = @_;
+
+ my $count = scalar @lines;
+ return unless $count;
+
+ my @report;
+ push @report, '';
+ push @report, '**';
+ push @report, "** $title ($count)";
+ push @report, "** [ $action ]";
+ push @report, '**';
+ push @report, '';
+
+ my $max_length = 0;
+ foreach my $rh (@lines) {
+ $max_length = length($rh->{mail}) if length($rh->{mail}) > $max_length;
+ }
+
+ foreach my $rh (@lines) {
+ my $template = "%-${max_length}s %s";
+ my @fields = ($rh->{mail}, $rh->{name});
+
+ if ($rh->{bugmail}) {
+ $template .= ' (%s)';
+ push @fields, $rh->{bugmail};
+ };
+
+ push @report, sprintf($template, @fields);
+ }
+
+ return @report;
+}
+
+sub email_report {
+ my ($report, $subject, @recipients) = @_;
+ unshift @$report, (
+ "Subject: $subject",
+ 'X-Bugzilla-Type: moco-ldap-check',
+ 'From: ' . REPORT_SENDER,
+ 'To: ' . join(',', @recipients),
+ );
+ if ($debug) {
+ print "\n", join("\n", @$report), "\n";
+ } else {
+ MessageToMTA(join("\n", @$report));
+ }
+}
+
+sub clean_email {
+ my $email = shift;
+ $email = trim($email);
+ $email = $1 if $email =~ /^(\S+)/;
+ $email =~ s/&#64;/@/;
+ $email = lc $email;
+ return $email;
+}
+
+sub canon_email {
+ my $email = shift;
+ $email = clean_email($email);
+ $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/;
+ return $email;
+}
+
+sub trim {
+ my $value = shift;
+ $value =~ s/(^\s+|\s+$)//g;
+ return $value;
+}
+
+sub serialise {
+ my ($filename, $ref) = @_;
+ local $Data::Dumper::Purity = 1;
+ local $Data::Dumper::Deepcopy = 1;
+ local $Data::Dumper::Sortkeys = 1;
+ write_file($filename, Dumper($ref));
+}
+
+sub deserialise {
+ my ($filename) = @_;
+ return unless -s $filename;
+ my $cpt = Safe->new();
+ $cpt->reval('our ' . read_file($filename))
+ || die "$!";
+ return ${$cpt->varglob('VAR1')};
+}
+
diff --git a/contrib/nagios_blocker_checker.pl b/contrib/nagios_blocker_checker.pl
new file mode 100755
index 000000000..bbc08b629
--- /dev/null
+++ b/contrib/nagios_blocker_checker.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin/..";
+use lib "$Bin/../lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::User qw(login_to_id);
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+# Time in hours to wait before paging/warning
+
+use constant ALERT_TIMES => {
+ 'major.alarm' => 24,
+ 'major.warn' => 20,
+ 'critical.alarm' => 8,
+ 'critical.warn' => 5,
+ 'blocker.alarm' => 0,
+ 'blocker.warn' => 0,
+};
+
+use constant NAGIOS_OK => 0;
+use constant NAGIOS_WARNING => 1;
+use constant NAGIOS_CRITICAL => 2;
+use constant NAGIOS_NAMES => [qw( OK WARNING CRITICAL )];
+
+my $assignee = shift
+ || die "Syntax: $0 assignee\neg. $0 server-ops\@mozilla-org.bugs\n";
+login_to_id($assignee, 1);
+
+my $sql = <<EOF;
+ SELECT bug_id, bug_severity, UNIX_TIMESTAMP(bugs.creation_ts) AS ts
+ FROM bugs
+ INNER JOIN profiles map_assigned_to ON bugs.assigned_to = map_assigned_to.userid
+ WHERE map_assigned_to.login_name = ?
+ AND COALESCE(resolution, '') = ''
+ AND bug_severity IN ('blocker', 'critical', 'major')
+EOF
+
+my $bugs = {
+ 'major' => [],
+ 'critical' => [],
+ 'blocker' => [],
+};
+my $current_state = NAGIOS_OK;
+my $current_time = time;
+
+my $dbh = Bugzilla->switch_to_shadow_db;
+foreach my $bug (@{ $dbh->selectall_arrayref($sql, { Slice => {} }, $assignee) }) {
+ my $severity = $bug->{bug_severity};
+ my $age = ($current_time - $bug->{ts}) / 3600;
+
+ if ($age > ALERT_TIMES->{"$severity.alarm"}) {
+ $current_state = NAGIOS_CRITICAL;
+ push @{$bugs->{$severity}}, "https://bugzil.la/" . $bug->{bug_id};
+
+ } elsif ($age > ALERT_TIMES->{"$severity.warn"}) {
+ if ($current_state < NAGIOS_WARNING) {
+ $current_state = NAGIOS_WARNING;
+ }
+ push @{$bugs->{$severity}}, "https://bugzil.la/" . $bug->{bug_id};
+
+ }
+}
+
+print "bugs " . NAGIOS_NAMES->[$current_state] . ": ";
+if ($current_state == NAGIOS_OK) {
+ print "No blocker, critical, or major bugs found."
+}
+foreach my $severity (qw( blocker critical major )) {
+ my $list = $bugs->{$severity};
+ if (@$list) {
+ printf "%s %s bug(s) found " . join(' , ', @$list) . " ", scalar(@$list), $severity;
+ }
+}
+print "\n";
+
+exit $current_state;
diff --git a/contrib/new-yui3.pl b/contrib/new-yui3.pl
new file mode 100755
index 000000000..2d1eeddc2
--- /dev/null
+++ b/contrib/new-yui3.pl
@@ -0,0 +1,80 @@
+#!/usr/bin/perl -w
+#
+# Updates the version of YUI3 used by Bugzilla. Just pass the path to
+# an unzipped yui release directory, like:
+#
+# contrib/new-yui3.pl /path/to/yui3/
+#
+
+use strict;
+
+use FindBin;
+use File::Find;
+use File::Basename;
+
+use constant EXCLUDES => qw(
+ gallery-*
+);
+
+sub usage {
+ my $error = shift;
+ print "$error\n";
+ print <<USAGE;
+Usage: contrib/new-yui3.pl /path/to/yui3/files
+
+Eg. contrib/new-yui3.pl /home/dkl/downloads/yui3
+The yui3 directory should contain the 'build' directory
+from the downloaded YUI3 tarball containing the module
+related files.
+USAGE
+ exit(1);
+}
+
+#############
+# Main Code #
+#############
+
+my $SOURCE_PATH = shift;
+my $DEST_PATH = "$FindBin::Bin/../js/yui3";
+
+if (!$SOURCE_PATH || !-d "$SOURCE_PATH/build") {
+ usage("Source path not found!");
+}
+
+mkdir($DEST_PATH) unless -d $DEST_PATH;
+
+my $exclude_string = join(" ", map { "--exclude $_" } EXCLUDES);
+my $command = "rsync -av --delete $exclude_string " .
+ "$SOURCE_PATH/build/ $DEST_PATH/";
+system($command) == 0 or usage("system '$command' failed: $?");
+
+find(
+ sub {
+ my $delete = 0;
+ my $filename = basename $File::Find::name;
+ if ($filename =~ /-debug\.js$/
+ || $filename =~ /-coverage\.js$/)
+ {
+ $delete = 1;
+ }
+ elsif ($filename =~ /-skin\.css$/) {
+ my $temp_filename = $filename;
+ $temp_filename =~ s/-skin//;
+ if (-e $temp_filename) {
+ $delete = 1;
+ }
+ }
+ elsif ($filename =~ /-min\.js/) {
+ $filename =~ s/-min//;
+ if (-e $filename) {
+ $delete = 1;
+ }
+ }
+ return if !$delete;
+ print "deleting $filename\n";
+ unlink($filename) || usage($!);
+ },
+ $DEST_PATH
+);
+
+exit(0);
diff --git a/contrib/recode.pl b/contrib/recode.pl
index f8de12eb1..e74e06c07 100755
--- a/contrib/recode.pl
+++ b/contrib/recode.pl
@@ -42,8 +42,10 @@ use constant MAX_STRING_LEN => 25;
# For certain tables, we can't automatically determine their Primary Key.
# So, we specify it here as a string.
use constant SPECIAL_KEYS => {
+ # bugs_activity since 4.4 has a unique primary key added
bugs_activity => 'bug_id,bug_when,fieldid',
profile_setting => 'user_id,setting_name',
+ # profiles_activity since 4.4 has a unique primary key added
profiles_activity => 'userid,profiles_when,fieldid',
setting_value => 'name,value',
# longdescs didn't used to have a PK, before 2.20.
diff --git a/contrib/reorg-tools/README b/contrib/reorg-tools/README
new file mode 100644
index 000000000..4e5d6eb4d
--- /dev/null
+++ b/contrib/reorg-tools/README
@@ -0,0 +1,9 @@
+Upstreaming attempt: https://bugzilla.mozilla.org/show_bug.cgi?id=616499
+
+Included in this directory is a group of tools we've used for moving components
+around in a Bugzilla 3.2 install on bugzilla.mozilla.org.
+
+They may require tweaking if you use them on your own install. Putting them
+here to make it easier to collaborate on them and keep them up-to-date.
+Hopefully Bugzilla upstream will be able to just do this from the web UI
+eventually.
diff --git a/contrib/reorg-tools/bmo-plan.txt b/contrib/reorg-tools/bmo-plan.txt
new file mode 100755
index 000000000..838ff0ab9
--- /dev/null
+++ b/contrib/reorg-tools/bmo-plan.txt
@@ -0,0 +1,82 @@
+==BMO Reorg Plan==
+
+Do the following things, mostly in order (but see "Timing" at the end):
+
+1) Create new classifications using GUI:
+ Graveyard (Description: "Old, retired products", sort key: <last>)
+
+2) Rename classifications using GUI:
+ Client Support to Other
+
+3) Move products between classification using GUI:
+ Grendel from Client Software to Graveyard
+ CCK from Unclassified to Graveyard
+ Derivatives from Unclassified to Graveyard
+ MozillaClassic from Unclassified to Graveyard
+ UI: "reclassify" link from the top-level classification list
+
+4) Create new products using GUI:
+ Core Graveyard in Graveyard
+ (desc: "Old, retired Core components", closed for entry, no charts)
+ MailNews Core in Components
+ (desc: "Mail and news components common to Thunderbird and SeaMonkey",
+ open for bug entry, create charts)
+
+5) Rename products using GUI, and fix queries using fixqueries.pl:
+mysql> update series_categories set name="SeaMonkey (2)" where id=32;
+ Mozilla Application Suite to SeaMonkey
+ Sumo to support.mozilla.com
+
+5.5) Rename versions and milestones in Toolkit to match Firefox before step 6
+
+6) Sync milestones, versions and groups between products using
+syncmsandversions.pl:
+ Core -> Core Graveyard (new)
+ Core -> MailNews Core (new)
+ Firefox -> Toolkit
+ Core -> SeaMonkey
+ mozilla.org -> Websites (only 1)
+
+6.5) Sync flag inclusions using syncflags.pl:
+ Core -> Core Graveyard (new)
+ Core -> MailNews Core (new)
+ Core -> SeaMonkey
+ mozilla.org -> Websites (only 1)
+
+6.7) Allow Firefox flags temporarily in Toolkit:
+ 250 | blocking-firefox3 | blocking1.9 - 387
+ 419 | blocking-firefox3.1 | blocking1.9.1 - 416
+ 63 | blocking0.8 | blocking1.6 - 69
+ 76 | blocking0.9 | blocking1.7 - 83
+ 36 | review | review - 4
+ 356 | wanted-firefox3 | wanted1.9 - 357
+ 418 | wanted-firefox3.1 | wanted1.9.1 - 417
+
+7) Move components using movecomponent.pl.
+ Any instruction beginning "moved from".
+ Can't fix the queries for this - oh well
+ <Very long list>
+
+8) Rename components using GUI, and fix queries using fixqueries.pl.
+ Any instruction beginning "renamed from" or "MailNews: prefix removed".
+ <Long list>
+
+9) Create new components using GUI.
+ Any instruction beginning "new".
+ <Long list>
+
+10) Move open bugs using GUI:
+ XP Miscellany to Core/General
+
+11) Merge components by moving bugs using GUI:
+ Any instruction beginning "merge in".
+ Merge all bugs, including closed. Delete empty component when done.
+ <long list of merges>
+
+12) Close Core Graveyard (and Grendel if necessary) to new bugs
+
+13) Rename Toolkit versions and milestones back (from 5.5)
+
+14) Execute flag mapping SQL using Reed's mapping to update bugs in Toolkit
+
+15) Disable above-listed flags in point 6.7 in Toolkit again
diff --git a/contrib/reorg-tools/fix_all_open_status_queries.pl b/contrib/reorg-tools/fix_all_open_status_queries.pl
new file mode 100755
index 000000000..b51ac21c2
--- /dev/null
+++ b/contrib/reorg-tools/fix_all_open_status_queries.pl
@@ -0,0 +1,140 @@
+#!/usr/bin/perl -w
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Status;
+use Bugzilla::Util;
+
+sub usage() {
+ print <<USAGE;
+Usage: fix_all_open_status_queries.pl <new_open_status>
+
+E.g.: fix_all_open_status_queries.pl READY
+This will add a new open state to user queries which currently look for
+all open bugs by listing every open status in their query criteria.
+For users who only look for bug_status=__open__, they will get the new
+open status automatically.
+USAGE
+}
+
+sub do_namedqueries {
+ my ($new_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $replace_count = 0;
+
+ my $query = $dbh->selectall_arrayref("SELECT id, query FROM namedqueries");
+
+ if ($query) {
+ $dbh->bz_start_transaction();
+
+ my $sth = $dbh->prepare("UPDATE namedqueries SET query = ? WHERE id = ?");
+
+ foreach my $row (@$query) {
+ my ($id, $old_query) = @$row;
+ my $new_query = all_open_states($new_status, $old_query);
+ if ($new_query) {
+ trick_taint($new_query);
+ $sth->execute($new_query, $id);
+ $replace_count++;
+ }
+ }
+
+ $dbh->bz_commit_transaction();
+ }
+
+ print "namedqueries: $replace_count replacements made.\n";
+}
+
+# series
+sub do_series {
+ my ($new_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $replace_count = 0;
+
+ my $query = $dbh->selectall_arrayref("SELECT series_id, query FROM series");
+
+ if ($query) {
+ $dbh->bz_start_transaction();
+
+ my $sth = $dbh->prepare("UPDATE series SET query = ? WHERE series_id = ?");
+
+ foreach my $row (@$query) {
+ my ($series_id, $old_query) = @$row;
+ my $new_query = all_open_states($new_status, $old_query);
+ if ($new_query) {
+ trick_taint($new_query);
+ $sth->execute($new_query, $series_id);
+ $replace_count++;
+ }
+ }
+
+ $dbh->bz_commit_transaction();
+ }
+
+ print "series: $replace_count replacements made.\n";
+}
+
+sub all_open_states {
+ my ($new_status, $query) = @_;
+
+ my @open_states = Bugzilla::Status::BUG_STATE_OPEN();
+ my $cgi = Bugzilla::CGI->new($query);
+ my @query_states = $cgi->param('bug_status');
+
+ my ($removed, $added) = diff_arrays(\@query_states, \@open_states);
+
+ if (scalar @$added == 1 && $added->[0] eq $new_status) {
+ push(@query_states, $new_status);
+ $cgi->param('bug_status', @query_states);
+ return $cgi->canonicalise_query();
+ }
+
+ return '';
+}
+
+sub validate_status {
+ my ($status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $exists = $dbh->selectrow_array("SELECT 1 FROM bug_status
+ WHERE value = ?",
+ undef, $status);
+ return $exists ? 1 : 0;
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 1) {
+ usage();
+ exit(1);
+}
+
+my ($new_status) = @ARGV;
+
+$new_status = uc($new_status);
+
+if (!validate_status($new_status)) {
+ print "Invalid status: $new_status\n\n";
+ usage();
+ exit(1);
+}
+
+print "Adding new status '$new_status'.\n\n";
+
+do_namedqueries($new_status);
+do_series($new_status);
+
+exit(0);
diff --git a/contrib/reorg-tools/fixgroupqueries.pl b/contrib/reorg-tools/fixgroupqueries.pl
new file mode 100755
index 000000000..1c75edb97
--- /dev/null
+++ b/contrib/reorg-tools/fixgroupqueries.pl
@@ -0,0 +1,119 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+ print <<USAGE;
+Usage: fixgroupqueries.pl <oldvalue> <newvalue>
+
+E.g.: fixgroupqueries.pl w-security webtools-security
+will change all occurrences of "w-security" to "webtools-security" in the
+appropriate places in the namedqueries.
+
+Note that all parameters are case-sensitive.
+USAGE
+}
+
+sub do_namedqueries($$) {
+ my ($old, $new) = @_;
+ $old = url_quote($old);
+ $new = url_quote($new);
+
+ my $dbh = Bugzilla->dbh;
+
+ my $replace_count = 0;
+ my $query = $dbh->selectall_arrayref("SELECT id, query FROM namedqueries");
+ if ($query) {
+ my $sth = $dbh->prepare("UPDATE namedqueries SET query = ?
+ WHERE id = ?");
+
+ foreach my $row (@$query) {
+ my ($id, $query) = @$row;
+ if (($query =~ /field\d+-\d+-\d+=bug_group/) &&
+ ($query =~ /(?:^|&|;)value\d+-\d+-\d+=$old(?:;|&|$)/)) {
+ $query =~ s/((?:^|&|;)value\d+-\d+-\d+=)$old(;|&|$)/$1$new$2/;
+ $sth->execute($query, $id);
+ $replace_count++;
+ }
+ }
+ }
+
+ print "namedqueries: $replace_count replacements made.\n";
+}
+
+# series
+sub do_series($$) {
+ my ($old, $new) = @_;
+ $old = url_quote($old);
+ $new = url_quote($new);
+
+ my $dbh = Bugzilla->dbh;
+ #$dbh->bz_start_transaction();
+
+ my $replace_count = 0;
+ my $query = $dbh->selectall_arrayref("SELECT series_id, query
+ FROM series");
+ if ($query) {
+ my $sth = $dbh->prepare("UPDATE series SET query = ?
+ WHERE series_id = ?");
+ foreach my $row (@$query) {
+ my ($series_id, $query) = @$row;
+
+ if (($query =~ /field\d+-\d+-\d+=bug_group/) &&
+ ($query =~ /(?:^|&|;)value\d+-\d+-\d+=$old(?:;|&|$)/)) {
+ $query =~ s/((?:^|&|;)value\d+-\d+-\d+=)$old(;|&|$)/$1$new$2/;
+ $sth->execute($query, $series_id);
+ $replace_count++;
+ }
+ }
+ }
+
+ #$dbh->bz_commit_transaction();
+ print "series: $replace_count replacements made.\n";
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+ usage();
+ exit();
+}
+
+my ($old, $new) = @ARGV;
+
+print "Changing all instances of '$old' to '$new'.\n\n";
+
+#do_namedqueries($old, $new);
+do_series($old, $new);
+
+exit(0);
diff --git a/contrib/reorg-tools/fixqueries.pl b/contrib/reorg-tools/fixqueries.pl
new file mode 100755
index 000000000..4b862fd72
--- /dev/null
+++ b/contrib/reorg-tools/fixqueries.pl
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+ print <<USAGE;
+Usage: fixqueries.pl <parameter> <oldvalue> <newvalue>
+
+E.g.: fixqueries.pl product FoodReplicator SeaMonkey
+will change all occurrences of "FoodReplicator" to "Seamonkey" in the
+appropriate places in the namedqueries, series and series_categories tables.
+
+Note that all parameters are case-sensitive.
+USAGE
+}
+
+sub do_namedqueries($$$) {
+ my ($field, $old, $new) = @_;
+ $old = url_quote($old);
+ $new = url_quote($new);
+
+ my $dbh = Bugzilla->dbh;
+ #$dbh->bz_start_transaction();
+
+ my $replace_count = 0;
+ my $query = $dbh->selectall_arrayref("SELECT id, query FROM namedqueries");
+ if ($query) {
+ my $sth = $dbh->prepare("UPDATE namedqueries SET query = ?
+ WHERE id = ?");
+
+ foreach my $row (@$query) {
+ my ($id, $query) = @$row;
+ if ($query =~ /(?:^|&|;)$field=$old(?:&|$|;)/) {
+ $query =~ s/((?:^|&|;)$field=)$old(;|&|$)/$1$new$2/;
+ $sth->execute($query, $id);
+ $replace_count++;
+ }
+ }
+ }
+
+ #$dbh->bz_commit_transaction();
+ print "namedqueries: $replace_count replacements made.\n";
+}
+
+# series
+sub do_series($$$) {
+ my ($field, $old, $new) = @_;
+ $old = url_quote($old);
+ $new = url_quote($new);
+
+ my $dbh = Bugzilla->dbh;
+ #$dbh->bz_start_transaction();
+
+ my $replace_count = 0;
+ my $query = $dbh->selectall_arrayref("SELECT series_id, query
+ FROM series");
+ if ($query) {
+ my $sth = $dbh->prepare("UPDATE series SET query = ?
+ WHERE series_id = ?");
+ foreach my $row (@$query) {
+ my ($series_id, $query) = @$row;
+
+ if ($query =~ /(?:^|&|;)$field=$old(?:&|$|;)/) {
+ $query =~ s/((?:^|&|;)$field=)$old(;|&|$)/$1$new$2/;
+ $replace_count++;
+ }
+
+ $sth->execute($query, $series_id);
+ }
+ }
+
+ #$dbh->bz_commit_transaction();
+ print "series: $replace_count replacements made.\n";
+}
+
+# series_categories
+sub do_series_categories($$) {
+ my ($old, $new) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ $dbh->do("UPDATE series_categories SET name = ? WHERE name = ?",
+ undef,
+ ($new, $old));
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 3) {
+ usage();
+ exit();
+}
+
+my ($field, $old, $new) = @ARGV;
+
+print "Changing all instances of '$old' to '$new'.\n\n";
+
+do_namedqueries($field, $old, $new);
+do_series($field, $old, $new);
+do_series_categories($old, $new);
+
+exit(0);
+
diff --git a/contrib/reorg-tools/migrate_crash_signatures.pl b/contrib/reorg-tools/migrate_crash_signatures.pl
new file mode 100755
index 000000000..b12446280
--- /dev/null
+++ b/contrib/reorg-tools/migrate_crash_signatures.pl
@@ -0,0 +1,126 @@
+#!/usr/bin/perl
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+# FILE: migrate_crash_signatures.pl
+#
+# USAGE: ./migrate_crash_signatures.pl
+#
+# DESCRIPTION: Migrate current summary data on matched bugs to the
+# new cf_crash_signature custom fields.
+#
+# OPTIONS: No params, then performs dry-run without updating the database.
+# If a true value is passed as single argument, then the database
+# is updated.
+# REQUIREMENTS: None
+# BUGS: 577724
+# NOTES: None
+# AUTHOR: David Lawrence (dkl@mozilla.com),
+# COMPANY: Mozilla Corproation
+# VERSION: 1.0
+# CREATED: 05/31/2011 03:57:52 PM
+# REVISION: 1
+#===============================================================================
+
+use strict;
+use warnings;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+use Data::Dumper;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my $UPDATE_DB = shift; # Pass true value as single argument to perform database update
+
+my $dbh = Bugzilla->dbh;
+
+# User to make changes as
+my $user_id = $dbh->selectrow_array(
+ "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'");
+$user_id or die "Can't find user ID for 'nobody\@mozilla.org'\n";
+
+my $field_id = $dbh->selectrow_array(
+ "SELECT id FROM fielddefs WHERE name = 'cf_crash_signature'");
+$field_id or die "Can't find field ID for 'cf_crash_signature' field\n";
+
+# Search criteria
+# a) crash or topcrash keyword,
+# b) not have [notacrash] in whiteboard,
+# c) have a properly formulated [@ ...]
+
+# crash and topcrash keyword ids
+my $crash_keyword_id = $dbh->selectrow_array(
+ "SELECT id FROM keyworddefs WHERE name = 'crash'");
+$crash_keyword_id or die "Can't find keyword id for 'crash'\n";
+
+my $topcrash_keyword_id = $dbh->selectrow_array(
+ "SELECT id FROM keyworddefs WHERE name = 'topcrash'");
+$topcrash_keyword_id or die "Can't find keyword id for 'topcrash'\n";
+
+# main search query
+my $bugs = $dbh->selectall_arrayref("
+ SELECT bugs.bug_id, bugs.short_desc
+ FROM bugs LEFT JOIN keywords ON bugs.bug_id = keywords.bug_id
+ WHERE (keywords.keywordid = ? OR keywords.keywordid = ?)
+ AND bugs.status_whiteboard NOT REGEXP '\\\\[notacrash\\\\]'
+ AND bugs.short_desc REGEXP '\\\\[@.+\\\\]'
+ AND (bugs.cf_crash_signature IS NULL OR bugs.cf_crash_signature = '')
+ ORDER BY bugs.bug_id",
+ {'Slice' => {}}, $crash_keyword_id, $topcrash_keyword_id);
+
+my $bug_count = scalar @$bugs;
+$bug_count or die "No bugs were found in matching search criteria.\n";
+
+print "Migrating $bug_count bugs to new crash signature field\n";
+
+$dbh->bz_start_transaction() if $UPDATE_DB;
+
+foreach my $bug (@$bugs) {
+ my $bug_id = $bug->{'bug_id'};
+ my $summary = $bug->{'short_desc'};
+
+ print "Updating bug $bug_id ...";
+
+ my @signatures;
+ while ($summary =~ /(\[\@(?:\[.*\]|[^\[])*\])/g) {
+ push(@signatures, $1);
+ }
+
+ if (@signatures && $UPDATE_DB) {
+ my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+ $dbh->do("UPDATE bugs SET cf_crash_signature = ? WHERE bug_id = ?",
+ undef, join("\n", @signatures), $bug_id);
+ $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
+ "VALUES (?, ?, ?, ?, '', ?)",
+ undef, $bug_id, $user_id, $timestamp, $field_id, join("\n", @signatures));
+ $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
+ undef, $timestamp, $timestamp, $bug_id);
+ }
+ elsif (@signatures) {
+ print Dumper(\@signatures);
+ }
+
+ print "done.\n";
+}
+
+$dbh->bz_commit_transaction() if $UPDATE_DB;
diff --git a/contrib/reorg-tools/migrate_orange_bugs.pl b/contrib/reorg-tools/migrate_orange_bugs.pl
new file mode 100755
index 000000000..ae68b227c
--- /dev/null
+++ b/contrib/reorg-tools/migrate_orange_bugs.pl
@@ -0,0 +1,154 @@
+#!/usr/bin/perl -wT
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+#===============================================================================
+#
+# FILE: migrate_orange_bugs.pl
+#
+# USAGE: ./migrate_orange_bugs.pl [--remove]
+#
+# DESCRIPTION: Add intermittent-keyword to bugs with [orange] stored in
+# whiteboard field. If --remove, then also remove the [orange]
+# value from whiteboard.
+#
+# OPTIONS: Without --doit, does a dry-run without updating the database.
+# If --doit is passed, then the database is updated.
+# --remove will remove [orange] from the whiteboard.
+# REQUIREMENTS: None
+# BUGS: 791758
+# NOTES: None
+# AUTHOR: David Lawrence (dkl@mozilla.com),
+# COMPANY: Mozilla Corproation
+# VERSION: 1.0
+# CREATED: 10/31/2012
+# REVISION: 1
+#===============================================================================
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Field;
+use Bugzilla::User;
+use Bugzilla::Keyword;
+
+use Getopt::Long;
+use Term::ANSIColor qw(colored);
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my ($remove_whiteboard, $help, $doit);
+GetOptions("r|remove" => \$remove_whiteboard,
+ "h|help" => \$help, 'doit' => \$doit);
+
+sub usage {
+ my $error = shift || "";
+ print colored(['red'], $error) if $error;
+ print <<USAGE;
+Usage: migrate_orange_bugs.pl [--remove|-r] [--help|-h] [--doit]
+
+E.g.: migrate_orange_bugs.pl --remove --doit
+This script will add the intermittent-failure keyword to any bugs that
+contant [orange] in the status whiteboard. If the --remove option is
+given, then [orange] will be removed from the whiteboard as well.
+
+Pass --doit to make the database changes permanent.
+USAGE
+ exit(1);
+}
+
+# Exit if help was requested
+usage() if $help;
+
+# User to make changes as
+my $user_id = login_to_id('nobody@mozilla.org');
+$user_id or usage("Can't find user ID for 'nobody\@mozilla.org'\n");
+
+my $keywords_field_id = get_field_id('keywords');
+$keywords_field_id or usage("Can't find field ID for 'keywords' field\n");
+
+my $whiteboard_field_id = get_field_id('status_whiteboard');
+$whiteboard_field_id or usage("Can't find field ID for 'whiteboard' field\n");
+
+# intermittent-keyword id (assumes already created)
+my $keyword_obj = Bugzilla::Keyword->new({ name => 'intermittent-failure' });
+$keyword_obj or usage("Can't find keyword id for 'intermittent-failure'\n");
+my $keyword_id = $keyword_obj->id;
+
+my $dbh = Bugzilla->dbh;
+
+my $bugs = $dbh->selectall_arrayref("
+ SELECT DISTINCT bugs.bug_id, bugs.status_whiteboard
+ FROM bugs WHERE bugs.status_whiteboard LIKE '%[orange]%'
+ OR bugs.status_whiteboard LIKE '%[tb-orange]%'",
+ {'Slice' => {}});
+
+my $bug_count = scalar @$bugs;
+$bug_count or usage("No bugs were found in matching search criteria.\n");
+
+print colored(['green'], "Processing $bug_count [orange] bugs\n");
+
+$dbh->bz_start_transaction() if $doit;
+
+foreach my $bug (@$bugs) {
+ my $bug_id = $bug->{'bug_id'};
+ my $whiteboard = $bug->{'status_whiteboard'};
+
+ print "Checking bug $bug_id ... ";
+
+ my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+
+ my $keyword_present = $dbh->selectrow_array("
+ SELECT bug_id FROM keywords WHERE bug_id = ? AND keywordid = ?",
+ undef, $bug_id, $keyword_id);
+
+ if (!$keyword_present) {
+ print "adding keyword ... ";
+
+ if ($doit) {
+ $dbh->do("INSERT INTO keywords (bug_id, keywordid) VALUES (?, ?)",
+ undef, $bug_id, $keyword_id);
+ $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
+ "VALUES (?, ?, ?, ?, '', 'intermittent-failure')",
+ undef, $bug_id, $user_id, $timestamp, $keywords_field_id);
+ $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
+ undef, $timestamp, $timestamp, $bug_id);
+ }
+ }
+
+ if ($remove_whiteboard) {
+ print "removing whiteboard ... ";
+
+ if ($doit) {
+ my $old_whiteboard = $whiteboard;
+ $whiteboard =~ s/\[(tb-)?orange\]//ig;
+
+ $dbh->do("UPDATE bugs SET status_whiteboard = ? WHERE bug_id = ?",
+ undef, $whiteboard, $bug_id);
+ $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
+ "VALUES (?, ?, ?, ?, ?, ?)",
+ undef, $bug_id, $user_id, $timestamp, $whiteboard_field_id, $old_whiteboard, $whiteboard);
+ $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
+ undef, $timestamp, $timestamp, $bug_id);
+ }
+ }
+
+ print "done.\n";
+}
+
+$dbh->bz_commit_transaction() if $doit;
+
+if ($doit) {
+ print colored(['green'], "DATABASE WAS UPDATED\n");
+}
+else {
+ print colored(['red'], "DATABASE WAS NOT UPDATED\n");
+}
+
+exit(0);
diff --git a/contrib/reorg-tools/move_flag_types.pl b/contrib/reorg-tools/move_flag_types.pl
new file mode 100755
index 000000000..a75b7f497
--- /dev/null
+++ b/contrib/reorg-tools/move_flag_types.pl
@@ -0,0 +1,168 @@
+#!/usr/bin/perl
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+# FILE: move_flag_types.pl
+#
+# USAGE: ./move_flag_types.pl
+#
+# DESCRIPTION: Move current set flag from one type_id to another
+# based on product and optionally component.
+#
+# OPTIONS: ---
+# REQUIREMENTS: ---
+# BUGS: ---
+# NOTES: ---
+# AUTHOR: David Lawrence (:dkl), dkl@mozilla.com
+# COMPANY: Mozilla Foundation
+# VERSION: 1.0
+# CREATED: 08/22/2011 05:18:06 PM
+# REVISION: ---
+#===============================================================================
+
+=head1 NAME
+
+move_flag_types.pl - Move currently set flags from one type id to another based
+on product and optionally component.
+
+=head1 SYNOPSIS
+
+This script will move bugs matching a specific product (and optionally a component)
+from one flag type id to another if the bug has the flag set to either +, -, or ?.
+
+./move_flag_types.pl --old-id 4 --new-id 720 --product Firefox --component Installer
+
+=head1 OPTIONS
+
+=over
+
+=item B<--help|-h|?>
+
+Print a brief help message and exits.
+
+=item B<--oldid|-o>
+
+Old flag type id. Use editflagtypes.cgi to determine the type id from the URL.
+
+=item B<--newid|-n>
+
+New flag type id. Use editflagtypes.cgi to determine the type id from the URL.
+
+=item B<--product|-p>
+
+The product that the bugs most be assigned to.
+
+=item B<--component|-c>
+
+Optional: The component of the given product that the bugs must be assigned to.
+
+=item B<--doit|-d>
+
+Without this argument, changes are not actually committed to the database.
+
+=back
+
+=cut
+
+use strict;
+use warnings;
+
+use lib '.';
+
+use Bugzilla;
+use Getopt::Long;
+use Pod::Usage;
+
+my %params;
+GetOptions(\%params, 'help|h|?', 'oldid|o=s', 'newid|n=s',
+ 'product|p=s', 'component|c:s', 'doit|d') or pod2usage(1);
+
+if ($params{'help'} || !$params{'oldid'}
+ || !$params{'newid'} || !$params{'product'}) {
+ pod2usage({ -message => "Missing required argument",
+ -exitval => 1 });
+}
+
+# Set defaults
+$params{'doit'} ||= 0;
+$params{'component'} ||= '';
+
+my $dbh = Bugzilla->dbh;
+
+# Get the flag names
+my $old_flag_name = $dbh->selectrow_array(
+ "SELECT name FROM flagtypes WHERE id = ?",
+ undef, $params{'oldid'});
+my $new_flag_name = $dbh->selectrow_array(
+ "SELECT name FROM flagtypes WHERE id = ?",
+ undef, $params{'newid'});
+
+# Find the product id
+my $product_id = $dbh->selectrow_array(
+ "SELECT id FROM products WHERE name = ?",
+ undef, $params{'product'});
+
+# Find the component id if not __ANY__
+my $component_id;
+if ($params{'component'}) {
+ $component_id = $dbh->selectrow_array(
+ "SELECT id FROM components WHERE name = ? AND product_id = ?",
+ undef, $params{'component'}, $product_id);
+}
+
+my @query_args = ($params{'oldid'});
+
+my $flag_query = "SELECT flags.id AS flag_id, flags.bug_id AS bug_id
+ FROM flags JOIN bugs ON flags.bug_id = bugs.bug_id
+ WHERE flags.type_id = ? ";
+
+if ($component_id) {
+ # No need to compare against product_id as component_id is already
+ # tied to a specific product
+ $flag_query .= "AND bugs.component_id = ?";
+ push(@query_args, $component_id);
+}
+else {
+ # All bugs for a product regardless of component
+ $flag_query .= "AND bugs.product_id = ?";
+ push(@query_args, $product_id);
+}
+
+my $flags = $dbh->selectall_arrayref($flag_query, undef, @query_args);
+
+if (@$flags) {
+ print "Moving '" . scalar @$flags . "' flags " .
+ "from $old_flag_name (" . $params{'oldid'} . ") " .
+ "to $new_flag_name (" . $params{'newid'} . ")...\n";
+
+ if (!$params{'doit'}) {
+ print "Pass the argument --doit or -d to permanently make changes to the database.\n";
+ }
+ else {
+ my $flag_update_sth = $dbh->prepare("UPDATE flags SET type_id = ? WHERE id = ?");
+
+ foreach my $flag (@$flags) {
+ my ($flag_id, $bug_id) = @$flag;
+ print "Bug: $bug_id Flag: $flag_id\n";
+ $flag_update_sth->execute($params{'newid'}, $flag_id);
+ }
+ }
+}
+else {
+ print "No flags to move\n";
+}
diff --git a/contrib/reorg-tools/movebugs.pl b/contrib/reorg-tools/movebugs.pl
new file mode 100755
index 000000000..6d6a53b51
--- /dev/null
+++ b/contrib/reorg-tools/movebugs.pl
@@ -0,0 +1,172 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Cwd 'abs_path';
+use File::Basename;
+use FindBin;
+use lib "$FindBin::Bin/../..";
+use lib "$FindBin::Bin/../../lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::FlagType;
+use Bugzilla::Util;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 4) {
+ die <<USAGE;
+Usage: movebugs.pl <old-product> <old-component> <new-product> <new-component>
+
+Eg. movebugs.pl mozilla.org bmo bugzilla.mozilla.org admin
+Will move all bugs in the mozilla.org:bmo component to the
+bugzilla.mozilla.org:admin component.
+
+The new product must have matching versions, milestones, and flags from the old
+product (will be validated by this script).
+USAGE
+}
+
+my ($old_product, $old_component, $new_product, $new_component) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+my $old_product_id = $dbh->selectrow_array(
+ "SELECT id FROM products WHERE name=?",
+ undef, $old_product);
+$old_product_id
+ or die "Can't find product ID for '$old_product'.\n";
+
+my $old_component_id = $dbh->selectrow_array(
+ "SELECT id FROM components WHERE name=? AND product_id=?",
+ undef, $old_component, $old_product_id);
+$old_component_id
+ or die "Can't find component ID for '$old_component'.\n";
+
+my $new_product_id = $dbh->selectrow_array(
+ "SELECT id FROM products WHERE name=?",
+ undef, $new_product);
+$new_product_id
+ or die "Can't find product ID for '$new_product'.\n";
+
+my $new_component_id = $dbh->selectrow_array(
+ "SELECT id FROM components WHERE name=? AND product_id=?",
+ undef, $new_component, $new_product_id);
+$new_component_id
+ or die "Can't find component ID for '$new_component'.\n";
+
+my $product_field_id = $dbh->selectrow_array(
+ "SELECT id FROM fielddefs WHERE name = 'product'");
+$product_field_id
+ or die "Can't find field ID for 'product' field\n";
+my $component_field_id = $dbh->selectrow_array(
+ "SELECT id FROM fielddefs WHERE name = 'component'");
+$component_field_id
+ or die "Can't find field ID for 'component' field\n";
+
+my $user_id = $dbh->selectrow_array(
+ "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'");
+$user_id
+ or die "Can't find user ID for 'nobody\@mozilla.org'\n";
+
+$dbh->bz_start_transaction();
+
+# build list of bugs
+my $ra_ids = $dbh->selectcol_arrayref(
+ "SELECT bug_id FROM bugs WHERE product_id=? AND component_id=?",
+ undef, $old_product_id, $old_component_id);
+my $bug_count = scalar @$ra_ids;
+$bug_count
+ or die "No bugs were found in '$old_component'\n";
+my $where_sql = 'bug_id IN (' . join(',', @$ra_ids) . ')';
+
+# check versions
+my @missing_versions;
+my $ra_versions = $dbh->selectcol_arrayref(
+ "SELECT DISTINCT version FROM bugs WHERE $where_sql");
+foreach my $version (@$ra_versions) {
+ my $has_version = $dbh->selectrow_array(
+ "SELECT 1 FROM versions WHERE product_id=? AND value=?",
+ undef, $new_product_id, $version);
+ push @missing_versions, $version unless $has_version;
+}
+
+# check milestones
+my @missing_milestones;
+my $ra_milestones = $dbh->selectcol_arrayref(
+ "SELECT DISTINCT target_milestone FROM bugs WHERE $where_sql");
+foreach my $milestone (@$ra_milestones) {
+ my $has_milestone = $dbh->selectrow_array(
+ "SELECT 1 FROM milestones WHERE product_id=? AND value=?",
+ undef, $new_product_id, $milestone);
+ push @missing_milestones, $milestone unless $has_milestone;
+}
+
+# check flags
+my @missing_flags;
+my $ra_old_types = $dbh->selectcol_arrayref(
+ "SELECT DISTINCT type_id
+ FROM flags
+ INNER JOIN flagtypes ON flagtypes.id = flags.type_id
+ WHERE $where_sql");
+my $ra_new_types =
+ Bugzilla::FlagType::match({ product_id => $new_product_id,
+ component_id => $new_component_id });
+foreach my $old_type (@$ra_old_types) {
+ unless (grep { $_->id == $old_type } @$ra_new_types) {
+ my $flagtype = Bugzilla::FlagType->new($old_type);
+ push @missing_flags, $flagtype->name . ' (' . $flagtype->target_type . ')';
+ }
+}
+
+# show missing
+my $missing_error = '';
+if (@missing_versions) {
+ $missing_error .= "'$new_product' is missing the following version(s):\n " .
+ join("\n ", @missing_versions) . "\n";
+}
+if (@missing_milestones) {
+ $missing_error .= "'$new_product' is missing the following milestone(s):\n " .
+ join("\n ", @missing_milestones) . "\n";
+}
+if (@missing_flags) {
+ $missing_error .= "'$new_product'::'$new_component' is missing the following flag(s):\n " .
+ join("\n ", @missing_flags) . "\n";
+}
+die $missing_error if $missing_error;
+
+# confirmation
+print <<EOF;
+About to move $bug_count bugs
+From '$old_product' : '$old_component'
+To '$new_product' : '$new_component'
+
+Press <Ctrl-C> to stop or <Enter> to continue...
+EOF
+getc();
+
+print "Moving $bug_count bugs from $old_product:$old_component to $new_product:$new_component\n";
+
+# update bugs
+$dbh->do(
+ "UPDATE bugs SET product_id=?, component_id=? WHERE $where_sql",
+ undef, $new_product_id, $new_component_id);
+
+# touch bugs
+$dbh->do("UPDATE bugs SET delta_ts=NOW() WHERE $where_sql");
+$dbh->do("UPDATE bugs SET lastdiffed=NOW() WHERE $where_sql");
+
+# update bugs_activity
+$dbh->do(
+ "INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added)
+ SELECT bug_id, ?, delta_ts, ?, ?, ? FROM bugs WHERE $where_sql",
+ undef,
+ $user_id, $product_field_id, $old_product, $new_product);
+$dbh->do(
+ "INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added)
+ SELECT bug_id, ?, delta_ts, ?, ?, ? FROM bugs WHERE $where_sql",
+ undef,
+ $user_id, $component_field_id, $old_component, $new_component);
+
+$dbh->bz_commit_transaction();
+
diff --git a/contrib/reorg-tools/movecomponent.pl b/contrib/reorg-tools/movecomponent.pl
new file mode 100755
index 000000000..8f8bc0abc
--- /dev/null
+++ b/contrib/reorg-tools/movecomponent.pl
@@ -0,0 +1,193 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+#
+
+use strict;
+
+use Cwd 'abs_path';
+use File::Basename;
+BEGIN {
+ my $root = abs_path(dirname(__FILE__) . '/../..');
+ chdir($root);
+}
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+ print <<USAGE;
+Usage: movecomponent.pl <oldproduct> <newproduct> <component> <doit>
+
+E.g.: movecomponent.pl ReplicationEngine FoodReplicator SeaMonkey
+will move the component "SeaMonkey" from the product "ReplicationEngine"
+to the product "FoodReplicator".
+
+Important: You must make sure the milestones and versions of the bugs in the
+component are available in the new product. See syncmsandversions.pl.
+
+Pass in a true value for "doit" to make the database changes permament.
+USAGE
+
+ exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 3) {
+ usage();
+ exit();
+}
+
+my ($oldproduct, $newproduct, $component, $doit) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+$dbh->{'AutoCommit'} = 0 unless $doit; # Turn off autocommit by default
+
+# Find product IDs
+my $oldprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $oldproduct);
+if (!$oldprodid) {
+ print "Can't find product ID for '$oldproduct'.\n";
+ exit(1);
+}
+
+my $newprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $newproduct);
+if (!$newprodid) {
+ print "Can't find product ID for '$newproduct'.\n";
+ exit(1);
+}
+
+# Find component ID
+my $compid = $dbh->selectrow_array("SELECT id FROM components
+ WHERE name = ? AND product_id = ?",
+ undef, $component, $oldprodid);
+if (!$compid) {
+ print "Can't find component ID for '$component' in product " .
+ "'$oldproduct'.\n";
+ exit(1);
+}
+
+my $fieldid = $dbh->selectrow_array("SELECT id FROM fielddefs
+ WHERE name = 'product'");
+if (!$fieldid) {
+ print "Can't find field ID for 'product' field!\n";
+ exit(1);
+}
+
+# check versions
+my @missing_versions;
+my $ra_versions = $dbh->selectcol_arrayref(
+ "SELECT DISTINCT version FROM bugs WHERE component_id = ?",
+ undef, $compid);
+foreach my $version (@$ra_versions) {
+ my $has_version = $dbh->selectrow_array(
+ "SELECT 1 FROM versions WHERE product_id = ? AND value = ?",
+ undef, $newprodid, $version);
+ push @missing_versions, $version unless $has_version;
+}
+
+# check milestones
+my @missing_milestones;
+my $ra_milestones = $dbh->selectcol_arrayref(
+ "SELECT DISTINCT target_milestone FROM bugs WHERE component_id = ?",
+ undef, $compid);
+foreach my $milestone (@$ra_milestones) {
+ my $has_milestone = $dbh->selectrow_array(
+ "SELECT 1 FROM milestones WHERE product_id=? AND value=?",
+ undef, $newprodid, $milestone);
+ push @missing_milestones, $milestone unless $has_milestone;
+}
+
+my $missing_error = '';
+if (@missing_versions) {
+ $missing_error .= "'$newproduct' is missing the following version(s):\n " .
+ join("\n ", @missing_versions) . "\n";
+}
+if (@missing_milestones) {
+ $missing_error .= "'$newproduct' is missing the following milestone(s):\n " .
+ join("\n ", @missing_milestones) . "\n";
+}
+die $missing_error if $missing_error;
+
+# confirmation
+print <<EOF;
+About to move the component '$component'
+From '$oldproduct'
+To '$newproduct'
+
+Press <Ctrl-C> to stop or <Enter> to continue...
+EOF
+getc();
+
+print "Moving '$component' from '$oldproduct' to '$newproduct'...\n\n";
+$dbh->bz_start_transaction() if $doit;
+
+# Bugs table
+$dbh->do("UPDATE bugs SET product_id = ? WHERE component_id = ?",
+ undef,
+ ($newprodid, $compid));
+
+# Flags tables
+$dbh->do("UPDATE flaginclusions SET product_id = ? WHERE component_id = ?",
+ undef,
+ ($newprodid, $compid));
+
+$dbh->do("UPDATE flagexclusions SET product_id = ? WHERE component_id = ?",
+ undef,
+ ($newprodid, $compid));
+
+# Components
+$dbh->do("UPDATE components SET product_id = ? WHERE id = ?",
+ undef,
+ ($newprodid, $compid));
+
+# Mark bugs as touched
+$dbh->do("UPDATE bugs SET delta_ts = NOW()
+ WHERE component_id = ?", undef, $compid);
+$dbh->do("UPDATE bugs SET lastdiffed = NOW()
+ WHERE component_id = ?", undef, $compid);
+
+# Update bugs_activity
+my $userid = 1; # nobody@mozilla.org
+
+$dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed,
+ added)
+ SELECT bug_id, ?, delta_ts, ?, ?, ?
+ FROM bugs WHERE component_id = ?",
+ undef,
+ ($userid, $fieldid, $oldproduct, $newproduct, $compid));
+
+$dbh->bz_commit_transaction() if $doit;
+
+exit(0);
+
diff --git a/contrib/reorg-tools/reset_default_user.pl b/contrib/reorg-tools/reset_default_user.pl
new file mode 100755
index 000000000..42a7998de
--- /dev/null
+++ b/contrib/reorg-tools/reset_default_user.pl
@@ -0,0 +1,143 @@
+#!/usr/bin/perl -wT
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+
+use lib '.';
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::User;
+use Bugzilla::Field;
+use Bugzilla::Util qw(trick_taint);
+
+use Getopt::Long;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my $dbh = Bugzilla->dbh;
+
+my $field_name = "";
+my $product = "";
+my $component = "";
+my $help = "";
+my %user_cache = ();
+
+my $result = GetOptions('field=s' => \$field_name,
+ 'product=s' => \$product,
+ 'component=s' => \$component,
+ 'help|h' => \$help);
+
+sub usage {
+ print <<USAGE;
+Usage: reset_default_user.pl --field <fieldname> --product <product> [--component <component>] [--help]
+
+This script will load all bugs matching the product, and optionally component,
+and reset the default user value back to the default value for the component.
+Valid field names are assigned_to and qa_contact.
+USAGE
+}
+
+if (!$product || $help
+ || ($field_name ne 'assigned_to' && $field_name ne 'qa_contact'))
+{
+ usage();
+ exit(1);
+}
+
+# We will need these for entering into bugs_activity
+my $who = Bugzilla::User->new({ name => 'nobody@mozilla.org' });
+my $field = Bugzilla::Field->new({ name => $field_name });
+
+trick_taint($product);
+my $product_id = $dbh->selectrow_array(
+ "SELECT id FROM products WHERE name = ?",
+ undef, $product);
+$product_id or die "Can't find product ID for '$product'.\n";
+
+my $component_id;
+my $default_user_id;
+if ($component) {
+ trick_taint($component);
+ my $colname = $field->name eq 'qa_contact'
+ ? 'initialqacontact'
+ : 'initialowner';
+ ($component_id, $default_user_id) = $dbh->selectrow_array(
+ "SELECT id, $colname FROM components " .
+ "WHERE name = ? AND product_id = ?",
+ undef, $component, $product_id);
+ $component_id or die "Can't find component ID for '$component'.\n";
+ $user_cache{$default_user_id} ||= Bugzilla::User->new($default_user_id);
+}
+
+# build list of bugs
+my $bugs_query = "SELECT bug_id, qa_contact, component_id " .
+ "FROM bugs WHERE product_id = ?";
+my @args = ($product_id);
+
+if ($component_id) {
+ $bugs_query .= " AND component_id = ? AND qa_contact != ?";
+ push(@args, $component_id, $default_user_id);
+}
+
+my $bugs = $dbh->selectall_arrayref($bugs_query, {Slice => {}}, @args);
+my $bug_count = scalar @$bugs;
+$bug_count
+ or die "No bugs were found.\n";
+
+# confirmation
+print <<EOF;
+About to reset $field_name for $bug_count bugs.
+
+Press <Ctrl-C> to stop or <Enter> to continue...
+EOF
+getc();
+
+$dbh->bz_start_transaction();
+
+foreach my $bug (@$bugs) {
+ my $bug_id = $bug->{bug_id};
+ my $old_user_id = $bug->{$field->name};
+ my $old_comp_id = $bug->{component_id};
+
+ # If only changing one component, we already have the default user id
+ my $new_user_id;
+ if ($default_user_id) {
+ $new_user_id = $default_user_id;
+ }
+ else {
+ my $colname = $field->name eq 'qa_contact'
+ ? 'initialqacontact'
+ : 'initialowner';
+ $new_user_id = $dbh->selectrow_array(
+ "SELECT $colname FROM components WHERE id = ?",
+ undef, $old_comp_id);
+ }
+
+ if ($old_user_id != $new_user_id) {
+ print "Resetting " . $field->name . " for bug $bug_id ...";
+
+ # Use the cached version if already exists
+ my $old_user = $user_cache{$old_user_id} ||= Bugzilla::User->new($old_user_id);
+ my $new_user = $user_cache{$new_user_id} ||= Bugzilla::User->new($new_user_id);
+
+ my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+
+ $dbh->do("UPDATE bugs SET " . $field->name . " = ? WHERE bug_id = ?",
+ undef, $new_user_id, $bug_id);
+ $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
+ "VALUES (?, ?, ?, ?, ?, ?)",
+ undef, $bug_id, $who->id, $timestamp, $field->id, $old_user->login, $new_user->login);
+ $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
+ undef, $timestamp, $timestamp, $bug_id);
+
+ print "done.\n";
+ }
+}
+
+$dbh->bz_commit_transaction();
diff --git a/contrib/reorg-tools/syncflags.pl b/contrib/reorg-tools/syncflags.pl
new file mode 100755
index 000000000..6c5b8293a
--- /dev/null
+++ b/contrib/reorg-tools/syncflags.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+
+sub usage() {
+ print <<USAGE;
+Usage: syncflags.pl <srcproduct> <tgtproduct>
+
+E.g.: syncflags.pl FoodReplicator SeaMonkey
+will copy any flag inclusions (only) for the product "FoodReplicator"
+so matching inclusions exist for the product "SeaMonkey". This script is
+normally used prior to moving components from srcproduct to tgtproduct.
+USAGE
+
+ exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+ usage();
+ exit();
+}
+
+my ($srcproduct, $tgtproduct) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+# Find product IDs
+my $srcprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $srcproduct);
+if (!$srcprodid) {
+ print "Can't find product ID for '$srcproduct'.\n";
+ exit(1);
+}
+
+my $tgtprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $tgtproduct);
+if (!$tgtprodid) {
+ print "Can't find product ID for '$tgtproduct'.\n";
+ exit(1);
+}
+
+$dbh->do("INSERT INTO flaginclusions(component_id, type_id, product_id)
+ SELECT fi1.component_id, fi1.type_id, ? FROM flaginclusions fi1
+ LEFT JOIN flaginclusions fi2
+ ON fi1.type_id = fi2.type_id
+ AND fi2.product_id = ?
+ WHERE fi1.product_id = ?
+ AND fi2.type_id IS NULL",
+ undef,
+ $tgtprodid, $tgtprodid, $srcprodid);
+
+exit(0);
diff --git a/contrib/reorg-tools/syncmsandversions.pl b/contrib/reorg-tools/syncmsandversions.pl
new file mode 100755
index 000000000..1c3ce2154
--- /dev/null
+++ b/contrib/reorg-tools/syncmsandversions.pl
@@ -0,0 +1,121 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+
+sub usage() {
+ print <<USAGE;
+Usage: syncmsandversions.pl <srcproduct> <tgtproduct>
+
+E.g.: syncmsandversions.pl FoodReplicator SeaMonkey
+will copy any versions and milstones in the product "FoodReplicator"
+which do not exist in product "SeaMonkey" into it. This script is normally
+used prior to moving components from srcproduct to tgtproduct.
+USAGE
+
+ exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+ usage();
+ exit();
+}
+
+my ($srcproduct, $tgtproduct) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+# Find product IDs
+my $srcprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $srcproduct);
+if (!$srcprodid) {
+ print "Can't find product ID for '$srcproduct'.\n";
+ exit(1);
+}
+
+my $tgtprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+ undef, $tgtproduct);
+if (!$tgtprodid) {
+ print "Can't find product ID for '$tgtproduct'.\n";
+ exit(1);
+}
+
+$dbh->bz_start_transaction();
+
+$dbh->do("
+ INSERT INTO milestones(value, sortkey, isactive, product_id)
+ SELECT m1.value, m1.sortkey, m1.isactive, ?
+ FROM milestones m1
+ LEFT JOIN milestones m2 ON m1.value = m2.value
+ AND m2.product_id = ?
+ WHERE m1.product_id = ?
+ AND m2.value IS NULL
+ ",
+ undef,
+ $tgtprodid, $tgtprodid, $srcprodid);
+
+$dbh->do("
+ INSERT INTO versions(value, isactive, product_id)
+ SELECT v1.value, v1.isactive, ?
+ FROM versions v1
+ LEFT JOIN versions v2 ON v1.value = v2.value
+ AND v2.product_id = ?
+ WHERE v1.product_id = ?
+ AND v2.value IS NULL
+ ",
+ undef,
+ $tgtprodid, $tgtprodid, $srcprodid);
+
+$dbh->do("
+ INSERT INTO group_control_map (group_id, product_id, entry, membercontrol,
+ othercontrol, canedit, editcomponents,
+ editbugs, canconfirm)
+ SELECT g1.group_id, ?, g1.entry, g1.membercontrol, g1.othercontrol,
+ g1.canedit, g1.editcomponents, g1.editbugs, g1.canconfirm
+ FROM group_control_map g1
+ LEFT JOIN group_control_map g2 ON g1.product_id = ?
+ AND g2.product_id = ?
+ AND g1.group_id = g2.group_id
+ WHERE g1.product_id = ?
+ AND g2.group_id IS NULL
+ ",
+ undef,
+ $tgtprodid, $srcprodid, $tgtprodid, $srcprodid);
+
+$dbh->bz_commit_transaction();
+
+exit(0);
+
diff --git a/contrib/sanitizeme.pl b/contrib/sanitizeme.pl
new file mode 100755
index 000000000..7033006dd
--- /dev/null
+++ b/contrib/sanitizeme.pl
@@ -0,0 +1,195 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is the Mozilla
+# Corporation. Portions created by Mozilla are
+# Copyright (C) 2006 Mozilla Foundation. All Rights Reserved.
+#
+# Contributor(s): Myk Melez <myk@mozilla.org>
+# Alex Brugh <alex@cs.umn.edu>
+# Dave Miller <justdave@mozilla.com>
+# Byron Jones <glob@mozilla.com>
+
+use strict;
+
+use lib qw(.);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+use Getopt::Long;
+
+my $dbh = Bugzilla->dbh;
+
+# This SQL is designed to sanitize a copy of a Bugzilla database so that it
+# doesn't contain any information that can't be viewed from a web browser by
+# a user who is not logged in.
+
+# Last validated against Bugzilla version 4.0
+
+my ($dry_run, $from_cron, $keep_attachments, $keep_groups,
+ $keep_passwords, $keep_insider, $trace, $enable_email) = (0, 0, 0, '', 0, 0, 0, 0);
+my $keep_groups_sql = '';
+
+GetOptions(
+ "dry-run" => \$dry_run,
+ "from-cron" => \$from_cron,
+ "keep-attachments" => \$keep_attachments,
+ "keep-passwords" => \$keep_passwords,
+ "keep-insider" => \$keep_insider,
+ "keep-groups:s" => \$keep_groups,
+ "trace" => \$trace,
+ "enable-email" => \$enable_email,
+) or exit;
+
+if ($keep_groups ne '') {
+ my @groups;
+ foreach my $group_id (split(/\s*,\s*/, $keep_groups)) {
+ my $group;
+ if ($group_id =~ /\D/) {
+ $group = Bugzilla::Group->new({ name => $group_id });
+ } else {
+ $group = Bugzilla::Group->new($group_id);
+ }
+ die "Invalid group '$group_id'\n" unless $group;
+ push @groups, $group->id;
+ }
+ $keep_groups_sql = "NOT IN (" . join(",", @groups) . ")";
+}
+
+$dbh->{TraceLevel} = 1 if $trace;
+
+if ($dry_run) {
+ print "** dry run : no changes to the database will be made **\n";
+ $dbh->bz_start_transaction();
+}
+eval {
+ delete_non_public_products();
+ delete_secure_bugs();
+ delete_insider_comments() unless $keep_insider;
+ delete_security_groups();
+ delete_sensitive_user_data();
+ delete_attachment_data() unless $keep_attachments;
+ disable_email_delivery() unless $enable_email;
+ print "All done!\n";
+ $dbh->bz_rollback_transaction() if $dry_run;
+};
+if ($@) {
+ $dbh->bz_rollback_transaction() if $dry_run;
+ die "$@" if $@;
+}
+
+sub delete_non_public_products {
+ # Delete all non-public products, and all data associated with them
+ my @products = Bugzilla::Product->get_all();
+ my $mandatory = CONTROLMAPMANDATORY;
+ foreach my $product (@products) {
+ # if there are any mandatory groups on the product, nuke it and
+ # everything associated with it (including the bugs)
+ Bugzilla->params->{'allowbugdeletion'} = 1; # override this in memory for now
+ my $mandatorygroups = $dbh->selectcol_arrayref("SELECT group_id FROM group_control_map WHERE product_id = ? AND (membercontrol = $mandatory)", undef, $product->id);
+ if (0 < scalar(@$mandatorygroups)) {
+ print "Deleting product '" . $product->name . "'...\n";
+ $product->remove_from_db();
+ }
+ }
+}
+
+sub delete_secure_bugs {
+ # Delete all data for bugs in security groups.
+ my $buglist = $dbh->selectall_arrayref(
+ $keep_groups
+ ? "SELECT DISTINCT bug_id FROM bug_group_map WHERE group_id $keep_groups_sql"
+ : "SELECT DISTINCT bug_id FROM bug_group_map"
+ );
+ $|=1; # disable buffering so the bug progress counter works
+ my $numbugs = scalar(@$buglist);
+ my $bugnum = 0;
+ print "Deleting $numbugs bugs in " . ($keep_groups ? 'non-' : '') . "security groups...\n";
+ foreach my $row (@$buglist) {
+ my $bug_id = $row->[0];
+ $bugnum++;
+ print "\r$bugnum/$numbugs" unless $from_cron;
+ my $bug = new Bugzilla::Bug($bug_id);
+ $bug->remove_from_db();
+ }
+ print "\rDone \n" unless $from_cron;
+}
+
+sub delete_insider_comments {
+ # Delete all 'insidergroup' comments and attachments
+ print "Deleting 'insidergroup' comments and attachments...\n";
+ $dbh->do("DELETE FROM longdescs WHERE isprivate = 1");
+ $dbh->do("DELETE attach_data FROM attachments JOIN attach_data ON attachments.attach_id = attach_data.id WHERE attachments.isprivate = 1");
+ $dbh->do("DELETE FROM attachments WHERE isprivate = 1");
+ $dbh->do("UPDATE bugs_fulltext SET comments = comments_noprivate");
+}
+
+sub delete_security_groups {
+ # Delete all security groups.
+ print "Deleting " . ($keep_groups ? 'non-' : '') . "security groups...\n";
+ $dbh->do("DELETE user_group_map FROM groups JOIN user_group_map ON groups.id = user_group_map.group_id WHERE groups.isbuggroup = 1");
+ $dbh->do("DELETE group_group_map FROM groups JOIN group_group_map ON (groups.id = group_group_map.member_id OR groups.id = group_group_map.grantor_id) WHERE groups.isbuggroup = 1");
+ $dbh->do("DELETE group_control_map FROM groups JOIN group_control_map ON groups.id = group_control_map.group_id WHERE groups.isbuggroup = 1");
+ $dbh->do("UPDATE flagtypes LEFT JOIN groups ON flagtypes.grant_group_id = groups.id SET grant_group_id = NULL WHERE groups.isbuggroup = 1");
+ $dbh->do("UPDATE flagtypes LEFT JOIN groups ON flagtypes.request_group_id = groups.id SET request_group_id = NULL WHERE groups.isbuggroup = 1");
+ if ($keep_groups) {
+ $dbh->do("DELETE FROM groups WHERE isbuggroup = 1 AND id $keep_groups_sql");
+ } else {
+ $dbh->do("DELETE FROM groups WHERE isbuggroup = 1");
+ }
+}
+
+sub delete_sensitive_user_data {
+ # Remove sensitive user account data.
+ print "Deleting sensitive user account data...\n";
+ $dbh->do("UPDATE profiles SET cryptpassword = 'deleted'") unless $keep_passwords;
+ $dbh->do("DELETE FROM profiles_activity");
+ $dbh->do("DELETE FROM profile_search");
+ $dbh->do("DELETE FROM namedqueries");
+ $dbh->do("DELETE FROM tokens");
+ $dbh->do("DELETE FROM logincookies");
+ $dbh->do("DELETE FROM login_failure");
+ $dbh->do("DELETE FROM audit_log");
+ # queued bugmail
+ $dbh->do("DELETE FROM ts_error");
+ $dbh->do("DELETE FROM ts_exitstatus");
+ $dbh->do("DELETE FROM ts_funcmap");
+ $dbh->do("DELETE FROM ts_job");
+ $dbh->do("DELETE FROM ts_note");
+ # push extension messages
+ $dbh->do("DELETE FROM push");
+ $dbh->do("DELETE FROM push_backlog");
+ $dbh->do("DELETE FROM push_backoff");
+ $dbh->do("DELETE FROM push_log");
+ $dbh->do("DELETE FROM push_options");
+}
+
+sub delete_attachment_data {
+ # Delete unnecessary attachment data.
+ print "Removing attachment data to preserve disk space...\n";
+ $dbh->do("UPDATE attach_data SET thedata = ''");
+}
+
+sub disable_email_delivery {
+ # turn off email delivery for all users.
+ print "Turning off email delivery...\n";
+ $dbh->do("UPDATE profiles SET disable_mail = 1");
+
+ # Also clear out the default flag cc as well since they do not
+ # have to be in the profiles table
+ $dbh->do("UPDATE flagtypes SET cc_list = NULL");
+}
diff --git a/contrib/verify-user.pl b/contrib/verify-user.pl
new file mode 100755
index 000000000..d12cd745f
--- /dev/null
+++ b/contrib/verify-user.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Myk Melez <myk@mozilla.org>
+# Dave Miller <justdave@bugzilla.org>
+
+# See if a user account has ever done anything
+
+# ./verify-user.pl foo@baz.com
+
+use strict;
+
+use lib qw(.);
+
+use Bugzilla;
+use Bugzilla::Util;
+use Bugzilla::DB;
+use Bugzilla::Constants;
+
+# Make sure accounts were specified on the command line and exist.
+my $user = $ARGV[0] || die "You must specify an user.\n";
+my $dbh = Bugzilla->dbh;
+my $sth;
+
+#$sth = $dbh->prepare("SELECT name, count(*) as qty from bugs, products where reporter=198524 and product_id=products.id group by name order by qty desc");
+#$sth->execute();
+#my $results = $sth->fetchall_arrayref();
+#use Data::Dumper;
+#print Data::Dumper::Dumper($results);
+#exit;
+
+trick_taint($user);
+if ($user =~ /^\d+$/) { # user ID passed instead of email
+ $sth = $dbh->prepare('SELECT login_name FROM profiles WHERE userid = ?');
+ $sth->execute($user);
+ ($user) = $sth->fetchrow_array || die "The user with ID $ARGV[0] does not exist.\n";
+ print "User $ARGV[0]'s login name is $user.\n";
+}
+$sth = $dbh->prepare("SELECT userid FROM profiles WHERE login_name = ?");
+$sth->execute($user);
+my ($user_id) = $sth->fetchrow_array || die "The user $user does not exist.\n";
+
+print "${user}'s ID is $user_id.\n";
+
+$sth = $dbh->prepare("SELECT DISTINCT ipaddr FROM logincookies WHERE userid = ?");
+$sth->execute($user_id);
+my $iplist = $sth->fetchall_arrayref;
+if (@$iplist > 0) {
+ print "This user has recently connected from the following IP addresses:\n";
+ foreach my $ip (@$iplist) {
+ print $$ip[0] . "\n";
+ }
+}
+
+
+# A list of tables and columns to be checked.
+my $columns = {
+ attachments => ['submitter_id'] ,
+ bugs => ['assigned_to', 'reporter', 'qa_contact'] ,
+ bugs_activity => ['who'] ,
+ cc => ['who'] ,
+ components => ['initialowner', 'initialqacontact'] ,
+ flags => ['setter_id', 'requestee_id'] ,
+ logincookies => ['userid'] ,
+ longdescs => ['who'] ,
+ namedqueries => ['userid'] ,
+ profiles_activity => ['userid', 'who'] ,
+ quips => ['userid'] ,
+ series => ['creator'] ,
+ tokens => ['userid'] ,
+ user_group_map => ['user_id'] ,
+ votes => ['who'] ,
+ watch => ['watcher', 'watched'] ,
+
+};
+
+my $fields = 0;
+# Check records for user.
+foreach my $table (keys(%$columns)) {
+ foreach my $column (@{$columns->{$table}}) {
+ $sth = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE $column = ?");
+ if ($table eq 'user_group_map') {
+ $sth = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE $column = ? AND grant_type = " . GRANT_DIRECT);
+ }
+ $sth->execute($user_id);
+ my ($val) = $sth->fetchrow_array;
+ $fields++ if $val;
+ print "$table.$column: $val\n" if $val;
+ }
+}
+
+print "The user is mentioned in $fields fields.\n";
+
+if ($::ARGV[1] && $::ARGV[1] eq '-r') {
+ if ($fields == 0) {
+ $sth = $dbh->prepare("SELECT login_name FROM profiles WHERE login_name = ?");
+ my $count = 0;
+ print "Finding an unused recycle ID";
+ do {
+ $count++;
+ $sth->execute(sprintf("reuseme%03d\@bugzilla.org", $count));
+ print ".";
+ } while (my ($match) = $sth->fetchrow_array());
+ printf "\nUsing reuseme%03d\@bugzilla.org.\n", $count;
+ $dbh->do("DELETE FROM user_group_map WHERE user_id=?",undef,$user_id);
+ $dbh->do("UPDATE profiles SET realname='', cryptpassword='randomgarbage' WHERE userid=?",undef,$user_id);
+ $dbh->do("UPDATE profiles SET login_name=? WHERE userid=?",undef,sprintf("reuseme%03d\@bugzilla.org",$count),$user_id);
+ }
+ else {
+ print "Account has been used, so not recycling.\n";
+ }
+}
diff --git a/describecomponents.cgi b/describecomponents.cgi
index ee1361284..ed1f2388c 100755
--- a/describecomponents.cgi
+++ b/describecomponents.cgi
@@ -41,7 +41,9 @@ print $cgi->header();
# This script does nothing but displaying mostly static data.
Bugzilla->switch_to_shadow_db;
-my $product_name = trim($cgi->param('product') || '');
+my $product_name = trim($cgi->param('product') || '');
+my $component_mark = trim($cgi->param('component') || '');
+
my $product = new Bugzilla::Product({'name' => $product_name});
unless ($product && $user->can_access_product($product->name)) {
@@ -82,7 +84,8 @@ unless ($product && $user->can_access_product($product->name)) {
# End Data/Security Validation
######################################################################
-$vars->{'product'} = $product;
+$vars->{'product'} = $product;
+$vars->{'component_mark'} = $component_mark;
$template->process("reports/components.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
diff --git a/describekeywords.cgi b/describekeywords.cgi
index 9796b77d5..b8ed9bb48 100755
--- a/describekeywords.cgi
+++ b/describekeywords.cgi
@@ -38,7 +38,17 @@ my $vars = {};
# Run queries against the shadow DB.
Bugzilla->switch_to_shadow_db;
-$vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count();
+# Hide bug counts for security keywords from users who aren't a member of the
+# security group
+my $can_see_security = Bugzilla->user->in_group('security-group');
+my $keywords = Bugzilla::Keyword->get_all_with_bug_count();
+foreach my $keyword (@$keywords) {
+ $keyword->{'bug_count'} = 0
+ if $keyword->name =~ /^(?:sec|csec|wsec|opsec)-/
+ && !$can_see_security;
+}
+
+$vars->{'keywords'} = $keywords;
$vars->{'caneditkeywords'} = Bugzilla->user->in_group("editkeywords");
print Bugzilla->cgi->header();
diff --git a/docs/en/xml/using.xml b/docs/en/xml/using.xml
index 53766ef34..05b415021 100644
--- a/docs/en/xml/using.xml
+++ b/docs/en/xml/using.xml
@@ -1409,6 +1409,15 @@
their <quote>Field/recipient specific options</quote> setting.
</para>
+ <para>
+ The <quote>Ignore Bugs</quote> section lets you specify a
+ comma-separated list of bugs from which you never want to get any
+ email notification of any kind. Removing a bug from this list will
+ re-enable email notification for this bug. This is especially useful
+ e.g. if you are the reporter of a very noisy bug which you are not
+ interested in anymore or if you are watching someone who is in such
+ a noisy bug.
+ </para>
</section>
<section id="savedsearches" xreflabel="Saved Searches">
diff --git a/editusers.cgi b/editusers.cgi
index 4182f6875..bd643e893 100755
--- a/editusers.cgi
+++ b/editusers.cgi
@@ -658,8 +658,17 @@ if ($action eq 'search') {
}
###########################################################################
-} elsif ($action eq 'activity') {
+} elsif ($action eq 'activity' || $action eq 'admin_activity') {
my $otherUser = check_user($otherUserID, $otherUserLogin);
+ my $activity_who = "profiles_activity.who";
+ my $activity_userid = "profiles_activity.userid";
+
+ if ($action eq 'admin_activity') {
+ $editusers || ThrowUserError("auth_failure", { group => "editusers",
+ action => "admin_activity",
+ object => "users" });
+ ($activity_userid, $activity_who) = ($activity_who, $activity_userid);
+ }
$vars->{'profile_changes'} = $dbh->selectall_arrayref(
"SELECT profiles.login_name AS who, " .
@@ -668,14 +677,15 @@ if ($action eq 'search') {
profiles_activity.oldvalue AS removed,
profiles_activity.newvalue AS added
FROM profiles_activity
- INNER JOIN profiles ON profiles_activity.who = profiles.userid
+ INNER JOIN profiles ON $activity_who = profiles.userid
INNER JOIN fielddefs ON fielddefs.id = profiles_activity.fieldid
- WHERE profiles_activity.userid = ?
+ WHERE $activity_userid = ?
ORDER BY profiles_activity.profiles_when",
{'Slice' => {}},
$otherUser->id);
$vars->{'otheruser'} = $otherUser;
+ $vars->{'action'} = $action;
$template->process("account/profile-activity.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
diff --git a/enter_bug.cgi b/enter_bug.cgi
index 5b684a965..55547b15c 100755
--- a/enter_bug.cgi
+++ b/enter_bug.cgi
@@ -51,6 +51,7 @@ use Bugzilla::Keyword;
use Bugzilla::Token;
use Bugzilla::Field;
use Bugzilla::Status;
+use Bugzilla::UserAgent;
my $user = Bugzilla->login(LOGIN_REQUIRED);
@@ -62,9 +63,21 @@ my $dbh = Bugzilla->dbh;
my $template = Bugzilla->template;
my $vars = {};
+# BMO add a hook for the guided extension
+Bugzilla::Hook::process('enter_bug_start', { vars => $vars });
+
# All pages point to the same part of the documentation.
$vars->{'doc_section'} = 'bugreports.html';
+if (!$vars->{'disable_guided'}) {
+ # Purpose: force guided format for newbies
+ $cgi->param(-name=>'format', -value=>'guided')
+ if !$cgi->param('format') && !$user->in_group('canconfirm');
+
+ $cgi->delete('format')
+ if ($cgi->param('format') && ($cgi->param('format') eq "__default__"));
+}
+
my $product_name = trim($cgi->param('product') || '');
# Will contain the product object the bug is created in.
my $product;
@@ -74,8 +87,14 @@ if ($product_name eq '') {
my @enterable_products = @{$user->get_enterable_products};
ThrowUserError('no_products') unless scalar(@enterable_products);
- my $classification = Bugzilla->params->{'useclassification'} ?
- scalar($cgi->param('classification')) : '__all';
+ # MOZILLA CUSTOMIZATION
+ # skip the classification selection page
+ my $classification;
+ if (Bugzilla->params->{'useclassification'}) {
+ $classification = scalar($cgi->param('classification')) || '__all';
+ } else {
+ $classification = '__all';
+ }
# Unless a real classification name is given, we sort products
# by classification.
@@ -166,198 +185,6 @@ sub formvalue {
return Bugzilla->cgi->param($name) || $default || "";
}
-# Takes the name of a field and a list of possible values for that
-# field. Returns the first value in the list that is actually a
-# valid value for that field.
-# The field should be named after its DB table.
-# Returns undef if none of the platforms match.
-sub pick_valid_field_value (@) {
- my ($field, @values) = @_;
- my $dbh = Bugzilla->dbh;
-
- foreach my $value (@values) {
- return $value if $dbh->selectrow_array(
- "SELECT 1 FROM $field WHERE value = ?", undef, $value);
- }
- return undef;
-}
-
-sub pickplatform {
- return formvalue("rep_platform") if formvalue("rep_platform");
-
- my @platform;
-
- if (Bugzilla->params->{'defaultplatform'}) {
- @platform = Bugzilla->params->{'defaultplatform'};
- } else {
- # If @platform is a list, this function will return the first
- # item in the list that is a valid platform choice. If
- # no choice is valid, we return "Other".
- for ($ENV{'HTTP_USER_AGENT'}) {
- #PowerPC
- /\(.*PowerPC.*\)/i && do {push @platform, ("PowerPC", "Macintosh");};
- #AMD64, Intel x86_64
- /\(.*amd64.*\)/ && do {push @platform, ("AMD64", "x86_64", "PC");};
- /\(.*x86_64.*\)/ && do {push @platform, ("AMD64", "x86_64", "PC");};
- #Intel Itanium
- /\(.*IA64.*\)/ && do {push @platform, "IA64";};
- #Intel x86
- /\(.*Intel.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- /\(.*[ix0-9]86.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- #Versions of Windows that only run on Intel x86
- /\(.*Win(?:dows |)[39M].*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- /\(.*Win(?:dows |)16.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- #Sparc
- /\(.*sparc.*\)/ && do {push @platform, ("Sparc", "Sun");};
- /\(.*sun4.*\)/ && do {push @platform, ("Sparc", "Sun");};
- #Alpha
- /\(.*AXP.*\)/i && do {push @platform, ("Alpha", "DEC");};
- /\(.*[ _]Alpha.\D/i && do {push @platform, ("Alpha", "DEC");};
- /\(.*[ _]Alpha\)/i && do {push @platform, ("Alpha", "DEC");};
- #MIPS
- /\(.*IRIX.*\)/i && do {push @platform, ("MIPS", "SGI");};
- /\(.*MIPS.*\)/i && do {push @platform, ("MIPS", "SGI");};
- #68k
- /\(.*68K.*\)/ && do {push @platform, ("68k", "Macintosh");};
- /\(.*680[x0]0.*\)/ && do {push @platform, ("68k", "Macintosh");};
- #HP
- /\(.*9000.*\)/ && do {push @platform, ("PA-RISC", "HP");};
- #ARM
- /\(.*ARM.*\)/ && do {push @platform, ("ARM", "PocketPC");};
- #PocketPC intentionally before PowerPC
- /\(.*Windows CE.*PPC.*\)/ && do {push @platform, ("ARM", "PocketPC");};
- #PowerPC
- /\(.*PPC.*\)/ && do {push @platform, ("PowerPC", "Macintosh");};
- /\(.*AIX.*\)/ && do {push @platform, ("PowerPC", "Macintosh");};
- #Stereotypical and broken
- /\(.*Windows CE.*\)/ && do {push @platform, ("ARM", "PocketPC");};
- /\(.*Macintosh.*\)/ && do {push @platform, ("68k", "Macintosh");};
- /\(.*Mac OS [89].*\)/ && do {push @platform, ("68k", "Macintosh");};
- /\(.*Win64.*\)/ && do {push @platform, "IA64";};
- /\(Win.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- /\(.*Win(?:dows[ -])NT.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
- /\(.*OSF.*\)/ && do {push @platform, ("Alpha", "DEC");};
- /\(.*HP-?UX.*\)/i && do {push @platform, ("PA-RISC", "HP");};
- /\(.*IRIX.*\)/i && do {push @platform, ("MIPS", "SGI");};
- /\(.*(SunOS|Solaris).*\)/ && do {push @platform, ("Sparc", "Sun");};
- #Braindead old browsers who didn't follow convention:
- /Amiga/ && do {push @platform, ("68k", "Macintosh");};
- /WinMosaic/ && do {push @platform, ("IA32", "x86", "PC");};
- }
- }
-
- return pick_valid_field_value('rep_platform', @platform) || "Other";
-}
-
-sub pickos {
- if (formvalue('op_sys') ne "") {
- return formvalue('op_sys');
- }
-
- my @os = ();
-
- if (Bugzilla->params->{'defaultopsys'}) {
- @os = Bugzilla->params->{'defaultopsys'};
- } else {
- # This function will return the first
- # item in @os that is a valid platform choice. If
- # no choice is valid, we return "Other".
- for ($ENV{'HTTP_USER_AGENT'}) {
- /\(.*IRIX.*\)/ && do {push @os, "IRIX";};
- /\(.*OSF.*\)/ && do {push @os, "OSF/1";};
- /\(.*Linux.*\)/ && do {push @os, "Linux";};
- /\(.*Solaris.*\)/ && do {push @os, "Solaris";};
- /\(.*SunOS.*\)/ && do {
- /\(.*SunOS 5.11.*\)/ && do {push @os, ("OpenSolaris", "Opensolaris", "Solaris 11");};
- /\(.*SunOS 5.10.*\)/ && do {push @os, "Solaris 10";};
- /\(.*SunOS 5.9.*\)/ && do {push @os, "Solaris 9";};
- /\(.*SunOS 5.8.*\)/ && do {push @os, "Solaris 8";};
- /\(.*SunOS 5.7.*\)/ && do {push @os, "Solaris 7";};
- /\(.*SunOS 5.6.*\)/ && do {push @os, "Solaris 6";};
- /\(.*SunOS 5.5.*\)/ && do {push @os, "Solaris 5";};
- /\(.*SunOS 5.*\)/ && do {push @os, "Solaris";};
- /\(.*SunOS.*sun4u.*\)/ && do {push @os, "Solaris";};
- /\(.*SunOS.*i86pc.*\)/ && do {push @os, "Solaris";};
- /\(.*SunOS.*\)/ && do {push @os, "SunOS";};
- };
- /\(.*HP-?UX.*\)/ && do {push @os, "HP-UX";};
- /\(.*BSD.*\)/ && do {
- /\(.*BSD\/(?:OS|386).*\)/ && do {push @os, "BSDI";};
- /\(.*FreeBSD.*\)/ && do {push @os, "FreeBSD";};
- /\(.*OpenBSD.*\)/ && do {push @os, "OpenBSD";};
- /\(.*NetBSD.*\)/ && do {push @os, "NetBSD";};
- };
- /\(.*BeOS.*\)/ && do {push @os, "BeOS";};
- /\(.*AIX.*\)/ && do {push @os, "AIX";};
- /\(.*OS\/2.*\)/ && do {push @os, "OS/2";};
- /\(.*QNX.*\)/ && do {push @os, "Neutrino";};
- /\(.*VMS.*\)/ && do {push @os, "OpenVMS";};
- /\(.*Win.*\)/ && do {
- /\(.*Windows XP.*\)/ && do {push @os, "Windows XP";};
- /\(.*Windows NT 6\.2.*\)/ && do {push @os, "Windows 8";};
- /\(.*Windows NT 6\.1.*\)/ && do {push @os, "Windows 7";};
- /\(.*Windows NT 6\.0.*\)/ && do {push @os, "Windows Vista";};
- /\(.*Windows NT 5\.2.*\)/ && do {push @os, "Windows Server 2003";};
- /\(.*Windows NT 5\.1.*\)/ && do {push @os, "Windows XP";};
- /\(.*Windows 2000.*\)/ && do {push @os, "Windows 2000";};
- /\(.*Windows NT 5.*\)/ && do {push @os, "Windows 2000";};
- /\(.*Win.*9[8x].*4\.9.*\)/ && do {push @os, "Windows ME";};
- /\(.*Win(?:dows |)M[Ee].*\)/ && do {push @os, "Windows ME";};
- /\(.*Win(?:dows |)98.*\)/ && do {push @os, "Windows 98";};
- /\(.*Win(?:dows |)95.*\)/ && do {push @os, "Windows 95";};
- /\(.*Win(?:dows |)16.*\)/ && do {push @os, "Windows 3.1";};
- /\(.*Win(?:dows[ -]|)NT.*\)/ && do {push @os, "Windows NT";};
- /\(.*Windows.*NT.*\)/ && do {push @os, "Windows NT";};
- };
- /\(.*Mac OS X.*\)/ && do {
- /\(.*Mac OS X (?:|Mach-O |\()10.8.*\)/ && do {push @os, "Mac OS X 10.8";};
- /\(.*Mac OS X (?:|Mach-O |\()10.7.*\)/ && do {push @os, "Mac OS X 10.7";};
- /\(.*Mac OS X (?:|Mach-O |\()10.6.*\)/ && do {push @os, "Mac OS X 10.6";};
- /\(.*Mac OS X (?:|Mach-O |\()10.5.*\)/ && do {push @os, "Mac OS X 10.5";};
- /\(.*Mac OS X (?:|Mach-O |\()10.4.*\)/ && do {push @os, "Mac OS X 10.4";};
- /\(.*Mac OS X (?:|Mach-O |\()10.3.*\)/ && do {push @os, "Mac OS X 10.3";};
- /\(.*Mac OS X (?:|Mach-O |\()10.2.*\)/ && do {push @os, "Mac OS X 10.2";};
- /\(.*Mac OS X (?:|Mach-O |\()10.1.*\)/ && do {push @os, "Mac OS X 10.1";};
- # Unfortunately, OS X 10.4 was the first to support Intel. This is
- # fallback support because some browsers refused to include the OS
- # Version.
- /\(.*Intel.*Mac OS X.*\)/ && do {push @os, "Mac OS X 10.4";};
- # OS X 10.3 is the most likely default version of PowerPC Macs
- # OS X 10.0 is more for configurations which didn't setup 10.x versions
- /\(.*Mac OS X.*\)/ && do {push @os, ("Mac OS X 10.3", "Mac OS X 10.0", "Mac OS X");};
- };
- /\(.*32bit.*\)/ && do {push @os, "Windows 95";};
- /\(.*16bit.*\)/ && do {push @os, "Windows 3.1";};
- /\(.*Mac OS \d.*\)/ && do {
- /\(.*Mac OS 9.*\)/ && do {push @os, ("Mac System 9.x", "Mac System 9.0");};
- /\(.*Mac OS 8\.6.*\)/ && do {push @os, ("Mac System 8.6", "Mac System 8.5");};
- /\(.*Mac OS 8\.5.*\)/ && do {push @os, "Mac System 8.5";};
- /\(.*Mac OS 8\.1.*\)/ && do {push @os, ("Mac System 8.1", "Mac System 8.0");};
- /\(.*Mac OS 8\.0.*\)/ && do {push @os, "Mac System 8.0";};
- /\(.*Mac OS 8[^.].*\)/ && do {push @os, "Mac System 8.0";};
- /\(.*Mac OS 8.*\)/ && do {push @os, "Mac System 8.6";};
- };
- /\(.*Darwin.*\)/ && do {push @os, ("Mac OS X 10.0", "Mac OS X");};
- # Silly
- /\(.*Mac.*\)/ && do {
- /\(.*Mac.*PowerPC.*\)/ && do {push @os, "Mac System 9.x";};
- /\(.*Mac.*PPC.*\)/ && do {push @os, "Mac System 9.x";};
- /\(.*Mac.*68k.*\)/ && do {push @os, "Mac System 8.0";};
- };
- # Evil
- /Amiga/i && do {push @os, "Other";};
- /WinMosaic/ && do {push @os, "Windows 95";};
- /\(.*PowerPC.*\)/ && do {push @os, "Mac System 9.x";};
- /\(.*PPC.*\)/ && do {push @os, "Mac System 9.x";};
- /\(.*68K.*\)/ && do {push @os, "Mac System 8.0";};
- }
- }
-
- push(@os, "Windows") if grep(/^Windows /, @os);
- push(@os, "Mac OS") if grep(/^Mac /, @os);
-
- return pick_valid_field_value('op_sys', @os) || "Other";
-}
##############################################################################
# End of subroutines
##############################################################################
@@ -420,19 +247,20 @@ $default{'product'} = $product->name;
if ($cloned_bug_id) {
- $default{'component_'} = $cloned_bug->component;
- $default{'priority'} = $cloned_bug->priority;
- $default{'bug_severity'} = $cloned_bug->bug_severity;
- $default{'rep_platform'} = $cloned_bug->rep_platform;
- $default{'op_sys'} = $cloned_bug->op_sys;
-
- $vars->{'short_desc'} = $cloned_bug->short_desc;
- $vars->{'bug_file_loc'} = $cloned_bug->bug_file_loc;
- $vars->{'keywords'} = $cloned_bug->keywords;
- $vars->{'dependson'} = join (", ", $cloned_bug_id, @{$cloned_bug->dependson});
- $vars->{'blocked'} = join (", ", @{$cloned_bug->blocked});
- $vars->{'deadline'} = $cloned_bug->deadline;
- $vars->{'estimated_time'} = $cloned_bug->estimated_time;
+ $default{'component_'} = $cloned_bug->component;
+ $default{'priority'} = $cloned_bug->priority;
+ $default{'bug_severity'} = $cloned_bug->bug_severity;
+ $default{'rep_platform'} = $cloned_bug->rep_platform;
+ $default{'op_sys'} = $cloned_bug->op_sys;
+
+ $vars->{'short_desc'} = $cloned_bug->short_desc;
+ $vars->{'bug_file_loc'} = $cloned_bug->bug_file_loc;
+ $vars->{'keywords'} = $cloned_bug->keywords;
+ $vars->{'dependson'} = join (", ", $cloned_bug_id, @{$cloned_bug->dependson});
+ $vars->{'blocked'} = join (", ", @{$cloned_bug->blocked});
+ $vars->{'deadline'} = $cloned_bug->deadline;
+ $vars->{'estimated_time'} = $cloned_bug->estimated_time;
+ $vars->{'status_whiteboard'} = $cloned_bug->status_whiteboard;
if (defined $cloned_bug->cc) {
$vars->{'cc'} = join (", ", @{$cloned_bug->cc});
@@ -468,12 +296,13 @@ if ($cloned_bug_id) {
} # end of cloned bug entry form
else {
-
$default{'component_'} = formvalue('component');
$default{'priority'} = formvalue('priority', Bugzilla->params->{'defaultpriority'});
$default{'bug_severity'} = formvalue('bug_severity', Bugzilla->params->{'defaultseverity'});
- $default{'rep_platform'} = pickplatform();
- $default{'op_sys'} = pickos();
+ $default{'rep_platform'} = formvalue('rep_platform',
+ Bugzilla->params->{'defaultplatform'} || detect_platform());
+ $default{'op_sys'} = formvalue('op_sys',
+ Bugzilla->params->{'defaultopsys'} || detect_op_sys());
$vars->{'alias'} = formvalue('alias');
$vars->{'short_desc'} = formvalue('short_desc');
diff --git a/errors/401.html b/errors/401.html
new file mode 100644
index 000000000..55c04398d
--- /dev/null
+++ b/errors/401.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Access Denied</title>
+ <style type="text/css">
+ body {
+ margin: 1em 2em;
+ background-color: #455372;
+ color: #ddd;
+ font-family: sans-serif;
+ }
+ h1, h3 {
+ color: #fff;
+ }
+ a {
+ color: #fff;
+ text-decoration: none;
+ }
+ #buggie {
+ float: left;
+ }
+ #content {
+ margin-left: 100px;
+ padding-top: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
+ <div id="content">
+ <h1>Authentication Required</h1>
+ <p>This server could not verify that you are authorized to access
+ that url. you either supplied the wrong credentials (e.g., bad
+ password), or your browser doesn't understand how to supply the
+ credentials required.</p>
+ <h3>Error 401</h3>
+ <p><a href="/">bugzilla.mozilla.org</a></p>
+ </div>
+ </body>
+</html>
diff --git a/errors/403.html b/errors/403.html
new file mode 100644
index 000000000..35325cfea
--- /dev/null
+++ b/errors/403.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Access Denied</title>
+ <style type="text/css">
+ body {
+ margin: 1em 2em;
+ background-color: #455372;
+ color: #ddd;
+ font-family: sans-serif;
+ }
+ h1, h3 {
+ color: #fff;
+ }
+ a {
+ color: #fff;
+ text-decoration: none;
+ }
+ #buggie {
+ float: left;
+ }
+ #content {
+ margin-left: 100px;
+ padding-top: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
+ <div id="content">
+ <h1>Access Denied</h1>
+ <p>Access to the requested resource has been denied.</p>
+ <h3>Error 403</h3>
+ <p><a href="/">bugzilla.mozilla.org</a></p>
+ </div>
+ </body>
+</html>
diff --git a/errors/404.html b/errors/404.html
new file mode 100644
index 000000000..56c72d0e2
--- /dev/null
+++ b/errors/404.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Object Not Found</title>
+ <style type="text/css">
+ body {
+ margin: 1em 2em;
+ background-color: #455372;
+ color: #ddd;
+ font-family: sans-serif;
+ }
+ h1, h3 {
+ color: #fff;
+ }
+ a {
+ color: #fff;
+ text-decoration: none;
+ }
+ #buggie {
+ float: left;
+ }
+ #content {
+ margin-left: 100px;
+ padding-top: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
+ <div id="content">
+ <h1>Object Not Found</h1>
+ <p>The requested URL was not found on this server.</p>
+ <h3>Error 404</h3>
+ <p><a href="/">bugzilla.mozilla.org</a></p>
+ </div>
+ </body>
+</html>
diff --git a/errors/500.html b/errors/500.html
new file mode 100644
index 000000000..2ffd6bad3
--- /dev/null
+++ b/errors/500.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Internal Server Error</title>
+ <style type="text/css">
+ body {
+ margin: 1em 2em;
+ background-color: #455372;
+ color: #ddd;
+ font-family: sans-serif;
+ }
+ h1, h3 {
+ color: #fff;
+ }
+ a {
+ color: #fff;
+ text-decoration: none;
+ }
+ #buggie {
+ float: left;
+ }
+ #content {
+ margin-left: 100px;
+ padding-top: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
+ <div id="content">
+ <h1>Internal Server Error</h1>
+ <p>The server encountered an internal error and was unable to complete your request.</p>
+ <h3>Error 500</h3>
+ <p><a href="/">bugzilla.mozilla.org</a></p>
+ </div>
+ </body>
+</html>
diff --git a/extensions/BMO/Config.pm b/extensions/BMO/Config.pm
new file mode 100644
index 000000000..0ad817768
--- /dev/null
+++ b/extensions/BMO/Config.pm
@@ -0,0 +1,38 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Gervase Markham
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::BMO;
+use strict;
+
+use constant NAME => 'BMO';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'Tie-IxHash',
+ module => 'Tie::IxHash',
+ version => 0
+ }
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
new file mode 100644
index 000000000..628b9ba09
--- /dev/null
+++ b/extensions/BMO/Extension.pm
@@ -0,0 +1,1136 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Gervase Markham.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+# David Lawrence <dkl@mozilla.com>
+# Byron Jones <glob@mozilla.com>
+
+package Bugzilla::Extension::BMO;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Field;
+use Bugzilla::Constants;
+use Bugzilla::Status;
+use Bugzilla::Product;
+use Bugzilla::User;
+use Bugzilla::User::Setting;
+use Bugzilla::Util qw(html_quote trick_taint trim datetime_from detaint_natural);
+use Bugzilla::Token;
+use Bugzilla::Error;
+use Bugzilla::Mailer;
+use Bugzilla::Util;
+
+use Scalar::Util qw(blessed);
+use Date::Parse;
+use DateTime;
+use Encode qw(find_encoding encode_utf8);
+use Sys::Syslog qw(:DEFAULT setlogsock);
+
+use Bugzilla::Extension::BMO::Constants;
+use Bugzilla::Extension::BMO::FakeBug;
+use Bugzilla::Extension::BMO::Data;
+use Bugzilla::Extension::BMO::Reports;
+
+our $VERSION = '0.1';
+
+#
+# Monkey-patched methods
+#
+
+BEGIN {
+ *Bugzilla::Bug::last_closed_date = \&_last_closed_date;
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ $vars->{'cf_hidden_in_product'} = \&cf_hidden_in_product;
+ $vars->{'cf_is_project_flag'} = \&cf_is_project_flag;
+ $vars->{'cf_flag_disabled'} = \&cf_flag_disabled;
+
+ if ($file =~ /^list\/list/) {
+ # Purpose: enable correct sorting of list table
+ # Matched to changes in list/table.html.tmpl
+ my %db_order_column_name_map = (
+ 'map_components.name' => 'component',
+ 'map_products.name' => 'product',
+ 'map_reporter.login_name' => 'reporter',
+ 'map_assigned_to.login_name' => 'assigned_to',
+ 'delta_ts' => 'opendate',
+ 'creation_ts' => 'changeddate',
+ );
+
+ my @orderstrings = split(/,\s*/, $vars->{'order'});
+
+ # contains field names of the columns being used to sort the table.
+ my @order_columns;
+ foreach my $o (@orderstrings) {
+ $o =~ s/bugs.//;
+ $o = $db_order_column_name_map{$o} if
+ grep($_ eq $o, keys(%db_order_column_name_map));
+ next if (grep($_ eq $o, @order_columns));
+ push(@order_columns, $o);
+ }
+
+ $vars->{'order_columns'} = \@order_columns;
+
+ # fields that have a custom sortkey. (So they are correctly sorted
+ # when using js)
+ my @sortkey_fields = qw(bug_status resolution bug_severity priority
+ rep_platform op_sys);
+
+ my %columns_sortkey;
+ foreach my $field (@sortkey_fields) {
+ $columns_sortkey{$field} = _get_field_values_sort_key($field);
+ }
+ $columns_sortkey{'target_milestone'} = _get_field_values_sort_key('milestones');
+
+ $vars->{'columns_sortkey'} = \%columns_sortkey;
+ }
+ elsif ($file =~ /^bug\/create\/create[\.-](.*)/) {
+ my $format = $1;
+ if (!$vars->{'cloned_bug_id'}) {
+ # Allow status whiteboard values to be bookmarked
+ $vars->{'status_whiteboard'} =
+ Bugzilla->cgi->param('status_whiteboard') || "";
+ }
+
+ # Purpose: for pretty product chooser
+ $vars->{'format'} = Bugzilla->cgi->param('format');
+
+ # Data needed for "this is a security bug" checkbox
+ $vars->{'sec_groups'} = \%product_sec_groups;
+
+ if ($format eq 'doc.html.tmpl') {
+ my $versions = Bugzilla::Product->new({ name => 'Core' })->versions;
+ $vars->{'versions'} = [ reverse @$versions ];
+ }
+ }
+
+
+ if ($file =~ /^list\/list/ || $file =~ /^bug\/create\/create[\.-]/) {
+ # hack to allow the bug entry templates to use check_can_change_field
+ # to see if various field values should be available to the current user.
+ $vars->{'default'} = Bugzilla::Extension::BMO::FakeBug->new($vars->{'default'} || {});
+ }
+
+ if ($file =~ /^attachment\/diff-header\./) {
+ my $attachid = $vars->{attachid} ? $vars->{attachid} : $vars->{newid};
+ $vars->{attachment} = Bugzilla::Attachment->new({ id => $attachid, cache => 1 })
+ if $attachid;
+ }
+}
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ if ($page eq 'user_activity.html') {
+ user_activity_report($vars);
+
+ } elsif ($page eq 'triage_reports.html') {
+ triage_reports($vars);
+
+ } elsif ($page eq 'upgrade-3.6.html') {
+ $vars->{'bzr_history'} = sub {
+ return `cd /data/www/bugzilla.mozilla.org; /usr/bin/bzr log -n0 -rlast:10..`;
+ };
+ }
+ elsif ($page eq 'fields.html') {
+ # Recently global/field-descs.none.tmpl and bug/field-help.none.tmpl
+ # were changed for better performance and are now only loaded once.
+ # I have not found an easy way to allow our hook template to check if
+ # it is called from pages/fields.html.tmpl. So we set a value in request_cache
+ # that our hook template can see.
+ Bugzilla->request_cache->{'bmo_fields_page'} = 1;
+ }
+ elsif ($page eq 'group_admins.html') {
+ group_admins_report($vars);
+ }
+ elsif ($page eq 'group_membership.html' or $page eq 'group_membership.txt') {
+ group_membership_report($page, $vars);
+ }
+ elsif ($page eq 'group_members.html' or $page eq 'group_members.json') {
+ group_members_report($vars);
+ }
+ elsif ($page eq 'email_queue.html') {
+ email_queue_report($vars);
+ }
+ elsif ($page eq 'release_tracking_report.html') {
+ release_tracking_report($vars);
+ }
+ elsif ($page eq 'query_database.html') {
+ query_database($vars);
+ }
+}
+
+sub _get_field_values_sort_key {
+ my ($field) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $fields = $dbh->selectall_arrayref(
+ "SELECT value, sortkey FROM $field
+ ORDER BY sortkey, value");
+
+ my %field_values;
+ foreach my $field (@$fields) {
+ my ($value, $sortkey) = @$field;
+ $field_values{$value} = $sortkey;
+ }
+ return \%field_values;
+}
+
+sub active_custom_fields {
+ my ($self, $args) = @_;
+ my $fields = $args->{'fields'};
+ my $params = $args->{'params'};
+ my $product = $params->{'product'};
+ my $component = $params->{'component'};
+
+ return if !$product;
+
+ my $product_name = blessed $product ? $product->name : $product;
+ my $component_name = blessed $component ? $component->name : $component;
+
+ my @tmp_fields;
+ foreach my $field (@$$fields) {
+ next if cf_hidden_in_product($field->name, $product_name, $component_name, $params->{'type'});
+ push(@tmp_fields, $field);
+ }
+ $$fields = \@tmp_fields;
+}
+
+sub cf_is_project_flag {
+ my ($field_name) = @_;
+ foreach my $flag_re (@$cf_project_flags) {
+ return 1 if $field_name =~ $flag_re;
+ }
+ return 0;
+}
+
+sub cf_hidden_in_product {
+ my ($field_name, $product_name, $component_name, $custom_flag_mode) = @_;
+
+ # If used in buglist.cgi, we pass in one_product which is a Bugzilla::Product
+ # elsewhere, we just pass the name of the product.
+ $product_name = blessed($product_name) ? $product_name->name
+ : $product_name;
+
+ # Also in buglist.cgi, we pass in a list of components instead
+ # of a single component name everywhere else.
+ my $component_list = [];
+ if ($component_name) {
+ $component_list = ref $component_name ? $component_name
+ : [ $component_name ];
+ }
+
+ if ($custom_flag_mode) {
+ if ($custom_flag_mode == 1) {
+ # skip custom flags
+ foreach my $flag_re (@$cf_flags) {
+ return 1 if $field_name =~ $flag_re;
+ }
+ } elsif ($custom_flag_mode == 2) {
+ # custom flags only
+ my $found = 0;
+ foreach my $flag_re (@$cf_flags) {
+ if ($field_name =~ $flag_re) {
+ $found = 1;
+ last;
+ }
+ }
+ return 1 unless $found;
+ }
+ }
+
+ foreach my $field_re (keys %$cf_visible_in_products) {
+ if ($field_name =~ $field_re) {
+ # If no product given, for example more than one product
+ # in buglist.cgi, then hide field by default
+ return 1 if !$product_name;
+
+ my $products = $cf_visible_in_products->{$field_re};
+ foreach my $product (keys %$products) {
+ my $components = $products->{$product};
+
+ my $found_component = 0;
+ if (@$components) {
+ foreach my $component (@$components) {
+ if (ref($component) eq 'Regexp') {
+ if (grep($_ =~ $component, @$component_list)) {
+ $found_component = 1;
+ last;
+ }
+ } else {
+ if (grep($_ eq $component, @$component_list)) {
+ $found_component = 1;
+ last;
+ }
+ }
+ }
+ }
+
+ # If product matches and at at least one component matches
+ # from component_list (if a matching component was required),
+ # we allow the field to be seen
+ if ($product eq $product_name && (!@$components || $found_component)) {
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+sub cf_flag_disabled {
+ my ($field_name, $bug) = @_;
+ return 0 unless grep { $field_name eq $_ } @$cf_disabled_flags;
+ my $value = $bug->{$field_name};
+ return $value eq '---' || $value eq '';
+}
+
+# Purpose: CC certain email addresses on bugmail when a bug is added or
+# removed from a particular group.
+sub bugmail_recipients {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+ my $recipients = $args->{'recipients'};
+ my $diffs = $args->{'diffs'};
+
+ if (@$diffs) {
+ # Changed bug
+ foreach my $ref (@$diffs) {
+ my $old = $ref->{old};
+ my $new = $ref->{new};
+ my $fieldname = $ref->{field_name};
+
+ if ($fieldname eq "bug_group") {
+ _cc_if_special_group($old, $recipients);
+ _cc_if_special_group($new, $recipients);
+ }
+ }
+ } else {
+ # Determine if it's a new bug, or a comment without a field change
+ my $comment_count = scalar @{$bug->comments};
+ if ($comment_count == 1) {
+ # New bug
+ foreach my $group (@{ $bug->groups_in }) {
+ _cc_if_special_group($group->{'name'}, $recipients);
+ }
+ }
+ }
+}
+
+sub _cc_if_special_group {
+ my ($group, $recipients) = @_;
+
+ return if !$group;
+
+ if (exists $group_change_notification{$group}) {
+ foreach my $login (@{ $group_change_notification{$group} }) {
+ my $id = login_to_id($login);
+ $recipients->{$id}->{+REL_CC} = Bugzilla::BugMail::BIT_DIRECT();
+ }
+ }
+}
+
+sub _check_trusted {
+ my ($field, $trusted, $priv_results) = @_;
+
+ my $needed_group = $trusted->{'_default'} || "";
+ foreach my $dfield (keys %$trusted) {
+ if ($field =~ $dfield) {
+ $needed_group = $trusted->{$dfield};
+ }
+ }
+ if ($needed_group && !Bugzilla->user->in_group($needed_group)) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+}
+
+sub _is_field_set {
+ my $value = shift;
+ return $value ne '---' && $value !~ /\?$/;
+}
+
+sub bug_check_can_change_field {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+ my $field = $args->{'field'};
+ my $new_value = $args->{'new_value'};
+ my $old_value = $args->{'old_value'};
+ my $priv_results = $args->{'priv_results'};
+ my $user = Bugzilla->user;
+
+ # Only users in the appropriate drivers group can change the
+ # cf_blocking_* fields or cf_tracking_* fields
+
+ if ($field =~ /^cf_(?:blocking|tracking)_/) {
+ # 0 -> 1 is used by show_bug, always allow so we skip this whole part
+ if (!($old_value eq '0' && $new_value eq '1')) {
+ # require privileged access to set a flag
+ if (_is_field_set($new_value)) {
+ _check_trusted($field, $blocking_trusted_setters, $priv_results);
+ }
+
+ # require editbugs to clear or re-nominate a set flag
+ elsif (_is_field_set($old_value)
+ && !$user->in_group('editbugs', $bug->{'product_id'}))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+
+ if ($new_value =~ /\?$/) {
+ _check_trusted($field, $blocking_trusted_requesters, $priv_results);
+ }
+ if ($user->id) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field =~ /^cf_status_/) {
+ # Only drivers can set wanted.
+ if ($new_value eq 'wanted') {
+ _check_trusted($field, $status_trusted_wanters, $priv_results);
+ } elsif (_is_field_set($new_value)) {
+ _check_trusted($field, $status_trusted_setters, $priv_results);
+ }
+ if ($user->id) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field =~ /^cf/ && !@$priv_results && $new_value ne '---') {
+ # "other" custom field setters restrictions
+ if (exists $other_setters->{$field}) {
+ my $in_group = 0;
+ foreach my $group (@{$other_setters->{$field}}) {
+ if ($user->in_group($group, $bug->product_id)) {
+ $in_group = 1;
+ last;
+ }
+ }
+ if (!$in_group) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+
+ } elsif ($field eq 'resolution' && $new_value eq 'EXPIRED') {
+ # The EXPIRED resolution should only be settable by gerv.
+ if ($user->login ne 'gerv@mozilla.org') {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+
+ } elsif ($field eq 'resolution' && $new_value eq 'FIXED') {
+ # You need at least canconfirm to mark a bug as FIXED
+ if (!$user->in_group('canconfirm', $bug->{'product_id'})) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+
+ } elsif (
+ ($field eq 'bug_status' && $old_value eq 'VERIFIED')
+ || ($field eq 'dup_id' && $bug->status->name eq 'VERIFIED')
+ || ($field eq 'resolution' && $bug->status->name eq 'VERIFIED')
+ ) {
+ # You need at least editbugs to reopen a resolved/verified bug
+ if (!$user->in_group('editbugs', $bug->{'product_id'})) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+
+ } elsif ($user->in_group('canconfirm', $bug->{'product_id'})) {
+ # Canconfirm is really "cantriage"; users with canconfirm can also mark
+ # bugs as DUPLICATE, WORKSFORME, and INCOMPLETE.
+ if ($field eq 'bug_status'
+ && is_open_state($old_value)
+ && !is_open_state($new_value))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+ elsif ($field eq 'resolution' &&
+ ($new_value eq 'DUPLICATE' ||
+ $new_value eq 'WORKSFORME' ||
+ $new_value eq 'INCOMPLETE'))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field eq 'bug_status') {
+ # Disallow reopening of bugs which have been resolved for > 1 year
+ if (is_open_state($new_value)
+ && !is_open_state($old_value)
+ && $bug->resolution eq 'FIXED')
+ {
+ my $days_ago = DateTime->now(time_zone => Bugzilla->local_timezone);
+ $days_ago->subtract(days => 365);
+ my $last_closed = datetime_from($bug->last_closed_date);
+ if ($last_closed lt $days_ago) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+ }
+}
+
+# link up various Mozilla-specific strings
+sub bug_format_comment {
+ my ($self, $args) = @_;
+ my $regexes = $args->{'regexes'};
+
+ # link UUIDs to crash-stats
+ # Only match if not already in an URL using the negative lookbehind (?<!\/)
+ push (@$regexes, {
+ match => qr/(?<!\/)\b(?:UUID\s+|bp\-)([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-
+ [a-f0-9]{4}\-[a-f0-9]{12})\b/x,
+ replace => sub {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+ return qq{<a href="https://crash-stats.mozilla.com/report/index/$match">bp-$match</a>};
+ }
+ });
+
+ # link to CVE/CAN security releases
+ push (@$regexes, {
+ match => qr/(?<!\/|=)\b((?:CVE|CAN)-\d{4}-\d{4})\b/,
+ replace => sub {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+ return qq{<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=$match">$match</a>};
+ }
+ });
+
+ # link to svn.m.o
+ push (@$regexes, {
+ match => qr/\br(\d{4,})\b/,
+ replace => sub {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+ return qq{<a href="http://viewvc.svn.mozilla.org/vc?view=rev&amp;revision=$match">r$match</a>};
+ }
+ });
+
+ # link bzr commit messages
+ push (@$regexes, {
+ match => qr/\b(Committing\sto:\sbzr\+ssh:\/\/
+ (?:[^\@]+\@)?(bzr\.mozilla\.org[^\n]+)\n.*?\bCommitted\s)
+ (revision\s(\d+))/sx,
+ replace => sub {
+ my $args = shift;
+ my $preamble = html_quote($args->{matches}->[0]);
+ my $url = html_quote($args->{matches}->[1]);
+ my $text = html_quote($args->{matches}->[2]);
+ my $id = html_quote($args->{matches}->[3]);
+ $url =~ s/\s+$//;
+ $url =~ s/\/$//;
+ return qq{$preamble<a href="http://$url/revision/$id">$text</a>};
+ }
+ });
+
+ # link to hg.m.o
+ # Note: for grouping in this regexp, always use non-capturing parentheses.
+ my $hgrepos = join('|', qw!(?:releases/)?comm-[\w.]+
+ (?:releases/)?mozilla-[\w.]+
+ (?:releases/)?mobile-[\w.]+
+ tracemonkey
+ tamarin-[\w.]+
+ camino!);
+
+ push (@$regexes, {
+ match => qr/\b(($hgrepos)\s+changeset:?\s+(?:\d+:)?([0-9a-fA-F]{12}))\b/,
+ replace => sub {
+ my $args = shift;
+ my $text = html_quote($args->{matches}->[0]);
+ my $repo = html_quote($args->{matches}->[1]);
+ my $id = html_quote($args->{matches}->[2]);
+ $repo = 'integration/mozilla-inbound' if $repo eq 'mozilla-inbound';
+ return qq{<a href="https://hg.mozilla.org/$repo/rev/$id">$text</a>};
+ }
+ });
+}
+
+# Purpose: make it always possible to file bugs in certain groups.
+sub bug_check_groups {
+ my ($self, $args) = @_;
+ my $group_names = $args->{'group_names'};
+ my $add_groups = $args->{'add_groups'};
+
+ return unless $group_names;
+ $group_names = ref $group_names
+ ? $group_names
+ : [ map { trim($_) } split(',', $group_names) ];
+
+ foreach my $name (@$group_names) {
+ if (exists $always_fileable_group{$name}) {
+ my $group = new Bugzilla::Group({ name => $name }) or next;
+ $add_groups->{$group->id} = $group;
+ }
+ }
+}
+
+# Purpose: generically handle generating pretty blocking/status "flags" from
+# custom field names.
+sub quicksearch_map {
+ my ($self, $args) = @_;
+ my $map = $args->{'map'};
+
+ foreach my $name (keys %$map) {
+ if ($name =~ /^cf_(blocking|tracking|status)_([a-z]+)?(\d+)?$/) {
+ my $type = $1;
+ my $product = $2;
+ my $version = $3;
+
+ if ($version) {
+ $version = join('.', split(//, $version));
+ }
+
+ my $pretty_name = $type;
+ if ($product) {
+ $pretty_name .= "-" . $product;
+ }
+ if ($version) {
+ $pretty_name .= $version;
+ }
+
+ $map->{$pretty_name} = $name;
+ }
+ elsif ($name =~ /cf_crash_signature$/) {
+ $map->{'sig'} = $name;
+ }
+ }
+}
+
+# Restrict content types attachable by non-privileged people
+my @mimetype_whitelist = ('^image\/', 'application\/pdf');
+
+sub object_end_of_create_validators {
+ my ($self, $args) = @_;
+ my $class = $args->{'class'};
+
+ if ($class->isa('Bugzilla::Attachment')) {
+ my $params = $args->{'params'};
+ my $bug = $params->{'bug'};
+ if (!Bugzilla->user->in_group('editbugs', $bug->product_id)) {
+ my $mimetype = $params->{'mimetype'};
+ if (!grep { $mimetype =~ /$_/ } @mimetype_whitelist ) {
+ # Need to neuter MIME type to something non-executable
+ if ($mimetype =~ /^text\//) {
+ $params->{'mimetype'} = "text/plain";
+ }
+ else {
+ $params->{'mimetype'} = "application/octet-stream";
+ }
+ }
+ }
+ }
+}
+
+# Automatically CC users to bugs based on group & product
+sub bug_end_of_create {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+
+ foreach my $group_name (keys %group_auto_cc) {
+ my $group_obj = Bugzilla::Group->new({ name => $group_name });
+ if ($group_obj && $bug->in_group($group_obj)) {
+ my $ra_logins = exists $group_auto_cc{$group_name}->{$bug->product}
+ ? $group_auto_cc{$group_name}->{$bug->product}
+ : $group_auto_cc{$group_name}->{'_default'};
+ foreach my $login (@$ra_logins) {
+ $bug->add_cc($login);
+ }
+ }
+ }
+}
+
+sub install_before_final_checks {
+ my ($self, $args) = @_;
+
+ # Add product chooser setting (although it was added long ago, so add_setting
+ # will just return every time).
+ add_setting('product_chooser',
+ ['pretty_product_chooser', 'full_product_chooser'],
+ 'pretty_product_chooser');
+
+ # Migrate from 'gmail_threading' setting to 'bugmail_new_prefix'
+ my $dbh = Bugzilla->dbh;
+ if ($dbh->selectrow_array("SELECT 1 FROM setting WHERE name='gmail_threading'")) {
+ $dbh->bz_start_transaction();
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='on-temp'
+ WHERE setting_name='gmail_threading' AND setting_value='Off'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='off'
+ WHERE setting_name='gmail_threading' AND setting_value='On'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='on'
+ WHERE setting_name='gmail_threading' AND setting_value='on-temp'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_name='bugmail_new_prefix'
+ WHERE setting_name='gmail_threading'");
+ $dbh->do("DELETE FROM setting WHERE name='gmail_threading'");
+ $dbh->bz_commit_transaction();
+ }
+}
+
+# Migrate old is_active stuff to new patch (is in core in 4.2), The old column
+# name was 'is_active', the new one is 'isactive' (no underscore).
+sub install_update_db {
+ my $dbh = Bugzilla->dbh;
+
+ if ($dbh->bz_column_info('milestones', 'is_active')) {
+ $dbh->do("UPDATE milestones SET isactive = 0 WHERE is_active = 0;");
+ $dbh->bz_drop_column('milestones', 'is_active');
+ $dbh->bz_drop_column('milestones', 'is_searchable');
+ }
+}
+
+sub _last_closed_date {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return $self->{'last_closed_date'} if defined $self->{'last_closed_date'};
+
+ my $closed_statuses = "'" . join("','", map { $_->name } closed_bug_statuses()) . "'";
+ my $status_field_id = get_field_id('bug_status');
+
+ $self->{'last_closed_date'} = $dbh->selectrow_array("
+ SELECT bugs_activity.bug_when
+ FROM bugs_activity
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.added IN ($closed_statuses)
+ AND bugs_activity.bug_id = ?
+ ORDER BY bugs_activity.bug_when DESC " . $dbh->sql_limit(1),
+ undef, $status_field_id, $self->id
+ );
+
+ return $self->{'last_closed_date'};
+}
+
+sub field_end_of_create {
+ my ($self, $args) = @_;
+ my $field = $args->{'field'};
+
+ # email mozilla's DBAs so they can update the grants for metrics
+ # this really should create a bug in mozilla.org/Server Operations: Database
+
+ if (Bugzilla->params->{'urlbase'} ne 'https://bugzilla.mozilla.org/') {
+ return;
+ }
+
+ if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) {
+ print "Emailing notification to infra-dbnotices\@mozilla.com\n";
+ }
+
+ my $name = $field->name;
+ my @message;
+ push @message, 'To: infra-dbnotices@mozilla.com';
+ push @message, "Subject: custom field '$name' added to bugzilla.mozilla.org";
+ push @message, 'From: ' . Bugzilla->params->{mailfrom};
+ push @message, '';
+ push @message, "The custom field '$name' has been added to the BMO database.";
+ push @message, '';
+ push @message, 'Please run the following on bugzilla1.db.scl3.mozilla.com:';
+ push @message, " GRANT SELECT ON `bugs`.`$name` TO 'metrics'\@'10.22.70.20_';";
+ push @message, " GRANT SELECT ($name) ON `bugs`.`bugs` TO 'metrics'\@'10.22.70.20_';";
+ push @message, " GRANT SELECT ON `bugs`.`$name` TO 'metrics'\@'10.22.70.21_';";
+ push @message, " GRANT SELECT ($name) ON `bugs`.`bugs` TO 'metrics'\@'10.22.70.21_';";
+ push @message, '';
+ MessageToMTA(join("\n", @message));
+}
+
+sub webservice {
+ my ($self, $args) = @_;
+
+ my $dispatch = $args->{dispatch};
+ $dispatch->{BMO} = "Bugzilla::Extension::BMO::WebService";
+}
+
+our $search_content_matches;
+BEGIN {
+ $search_content_matches = \&Bugzilla::Search::_content_matches;
+}
+
+sub search_operator_field_override {
+ my ($self, $args) = @_;
+ my $search = $args->{'search'};
+ my $operators = $args->{'operators'};
+
+ my $cgi = Bugzilla->cgi;
+ my @comments = $cgi->param('comments');
+ my $exclude_comments = scalar(@comments) && !grep { $_ eq '1' } @comments;
+
+ if ($cgi->param('query_format')
+ && $cgi->param('query_format') eq 'specific'
+ && $exclude_comments
+ ) {
+ # use the non-comment operator
+ $operators->{'content'}->{matches} = \&_short_desc_matches;
+ $operators->{'content'}->{notmatches} = \&_short_desc_matches;
+
+ } else {
+ # restore default content operator
+ $operators->{'content'}->{matches} = $search_content_matches;
+ $operators->{'content'}->{notmatches} = $search_content_matches;
+ }
+}
+
+sub _short_desc_matches {
+ # copy of Bugzilla::Search::_content_matches with comment searching removed
+
+ my ($self, $args) = @_;
+ my ($chart_id, $joins, $fields, $operator, $value) =
+ @$args{qw(chart_id joins fields operator value)};
+ my $dbh = Bugzilla->dbh;
+
+ # Add the fulltext table to the query so we can search on it.
+ my $table = "bugs_fulltext_$chart_id";
+ push(@$joins, { table => 'bugs_fulltext', as => $table });
+
+ # Create search terms to add to the SELECT and WHERE clauses.
+ my ($term, $rterm) =
+ $dbh->sql_fulltext_search("$table.short_desc", $value, 2);
+ $rterm = $term if !$rterm;
+
+ # The term to use in the WHERE clause.
+ if ($operator =~ /not/i) {
+ $term = "NOT($term)";
+ }
+ $args->{term} = $term;
+
+ my $current = $self->COLUMNS->{'relevance'}->{name};
+ $current = $current ? "$current + " : '';
+ # For NOT searches, we just add 0 to the relevance.
+ my $select_term = $operator =~ /not/ ? 0 : "($current$rterm)";
+ $self->COLUMNS->{'relevance'}->{name} = $select_term;
+}
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+ my $email = $args->{email};
+
+ _log_sent_email($email);
+
+ # see bug 844724
+ if ($email->header('to') && $email->header('to') eq 'sync-1@bugzilla.tld') {
+ $email->header_set('to', 'mei.kong@tcl.com');
+ }
+
+ # Add X-Bugzilla-Tracking header
+ if ($email->header('X-Bugzilla-ID')) {
+ my $bug_id = $email->header('X-Bugzilla-ID');
+
+ # return if we cannot successfully load the bug object
+ my $bug = new Bugzilla::Bug($bug_id);
+ return if !$bug;
+
+ # The BMO hook in active_custom_fields will filter
+ # the fields for us based on product and component
+ my @fields = Bugzilla->active_custom_fields({
+ product => $bug->product_obj,
+ component => $bug->component_obj,
+ type => 2,
+ });
+
+ my @set_values = ();
+ foreach my $field (@fields) {
+ my $field_name = $field->name;
+ next if cf_flag_disabled($field_name, $bug);
+ next if !$bug->$field_name || $bug->$field_name eq '---';
+ push(@set_values, $field->description . ":" . $bug->$field_name);
+ }
+
+ if (@set_values) {
+ $email->header_set('X-Bugzilla-Tracking' => join(' ', @set_values));
+ }
+ }
+
+ # attachments disabled, see bug 714488
+ return;
+
+ # If email is a request for a review, add the attachment itself
+ # to the email as an attachment. Attachment must be content type
+ # text/plain and below a certain size. Otherwise the email already
+ # contain a link to the attachment.
+ if ($email
+ && $email->header('X-Bugzilla-Type') eq 'request'
+ && ($email->header('X-Bugzilla-Flag-Requestee')
+ && $email->header('X-Bugzilla-Flag-Requestee') eq $email->header('to')))
+ {
+ my $body = $email->body;
+
+ if (my ($attach_id) = $body =~ /Attachment\s+(\d+)\s*:/) {
+ my $attachment = Bugzilla::Attachment->new($attach_id);
+ if ($attachment
+ && $attachment->ispatch
+ && $attachment->contenttype eq 'text/plain'
+ && $attachment->linecount
+ && $attachment->linecount < REQUEST_MAX_ATTACH_LINES)
+ {
+ # Don't send a charset header with attachments, as they might
+ # not be UTF-8, unless we can properly detect it.
+ my $charset;
+ if (Bugzilla->feature('detect_charset')) {
+ my $encoding = detect_encoding($attachment->data);
+ if ($encoding) {
+ $charset = find_encoding($encoding)->mime_name;
+ }
+ }
+
+ my $attachment_part = Email::MIME->create(
+ attributes => {
+ content_type => $attachment->contenttype,
+ filename => $attachment->filename,
+ disposition => "attachment",
+ },
+ body => $attachment->data,
+ );
+ $attachment_part->charset_set($charset) if $charset;
+
+ $email->parts_add([ $attachment_part ]);
+ }
+ }
+ }
+}
+
+# Log a summary of bugmail sent to the syslog, for auditing and monitoring
+sub _log_sent_email {
+ my $email = shift;
+
+ my $recipient = $email->header('to');
+ return unless $recipient;
+
+ my $subject = $email->header('Subject');
+
+ my $bug_id = $email->header('X-Bugzilla-ID');
+ if (!$bug_id && $subject =~ /[\[\(]Bug (\d+)/i) {
+ $bug_id = $1;
+ }
+ $bug_id = $bug_id ? "bug-$bug_id" : '-';
+
+ my $message_type;
+ my $type = $email->header('X-Bugzilla-Type');
+ my $reason = $email->header('X-Bugzilla-Reason');
+ if ($type eq 'whine' || $type eq 'request' || $type eq 'admin') {
+ $message_type = $type;
+ } elsif ($reason && $reason ne 'None') {
+ $message_type = $reason;
+ } else {
+ $message_type = $email->header('X-Bugzilla-Watch-Reason');
+ }
+ $message_type ||= '?';
+
+ $subject =~ s/[\[\(]Bug \d+[\]\)]\s*//;
+
+ openlog('apache', 'cons,pid', 'local4');
+ syslog('notice', encode_utf8("[bugmail] $recipient ($message_type) $bug_id $subject"));
+ closelog();
+}
+
+sub post_bug_after_creation {
+ my ($self, $args) = @_;
+ my $vars = $args->{vars};
+ my $bug = $vars->{bug};
+
+ if (Bugzilla->input_params->{format}
+ && Bugzilla->input_params->{format} eq 'employee-incident'
+ && $bug->component eq 'Server Operations: Desktop Issues')
+ {
+ my $error_mode_cache = Bugzilla->error_mode;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+
+ my ($investigate_bug, $ssh_key_bug);
+ my $old_user = Bugzilla->user;
+ eval {
+ Bugzilla->set_user(Bugzilla::User->new({ name => 'nobody@mozilla.org' }));
+ my $new_user = Bugzilla->user;
+
+ # HACK: User needs to be in the editbugs and primary bug's group to allow
+ # setting of dependencies.
+ $new_user->{'groups'} = [ Bugzilla::Group->new({ name => 'editbugs' }),
+ Bugzilla::Group->new({ name => 'infra' }),
+ Bugzilla::Group->new({ name => 'infrasec' }) ];
+
+ my $recipients = { changer => $new_user };
+ $vars->{original_reporter} = $old_user;
+
+ my $comment;
+ $cgi->param('display_action', '');
+ $template->process('bug/create/comment-employee-incident.txt.tmpl', $vars, \$comment)
+ || ThrowTemplateError($template->error());
+
+ $investigate_bug = Bugzilla::Bug->create({
+ short_desc => 'Investigate Lost Device',
+ product => 'mozilla.org',
+ component => 'Security Assurance: Incident',
+ status_whiteboard => '[infrasec:incident]',
+ bug_severity => 'critical',
+ cc => [ 'mcoates@mozilla.com', 'jstevensen@mozilla.com' ],
+ groups => [ 'infrasec' ],
+ comment => $comment,
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'other',
+ dependson => $bug->bug_id,
+ });
+ $bug->set_all({ blocked => { add => [ $investigate_bug->bug_id ] }});
+ Bugzilla::BugMail::Send($investigate_bug->id, $recipients);
+
+ Bugzilla->set_user($old_user);
+ $vars->{original_reporter} = '';
+ $comment = '';
+ $cgi->param('display_action', 'ssh');
+ $template->process('bug/create/comment-employee-incident.txt.tmpl', $vars, \$comment)
+ || ThrowTemplateError($template->error());
+
+ $ssh_key_bug = Bugzilla::Bug->create({
+ short_desc => 'Disable/Regenerate SSH Key',
+ product => $bug->product,
+ component => $bug->component,
+ bug_severity => 'critical',
+ cc => $bug->cc,
+ groups => [ map { $_->{name} } @{ $bug->groups } ],
+ comment => $comment,
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'other',
+ dependson => $bug->bug_id,
+ });
+ $bug->set_all({ blocked => { add => [ $ssh_key_bug->bug_id ] }});
+ Bugzilla::BugMail::Send($ssh_key_bug->id, $recipients);
+ };
+ my $error = $@;
+
+ Bugzilla->set_user($old_user);
+ Bugzilla->error_mode($error_mode_cache);
+
+ if ($error || !$investigate_bug || !$ssh_key_bug) {
+ warn "Failed to create additional employee-incident bug: $error" if $error;
+ $vars->{'message'} = 'employee_incident_creation_failed';
+ }
+ }
+}
+
+sub buglist_columns {
+ my ($self, $args) = @_;
+ my $columns = $args->{columns};
+ $columns->{'cc_count'} = {
+ name => '(SELECT COUNT(*) FROM cc WHERE cc.bug_id = bugs.bug_id)',
+ title => 'CC Count',
+ };
+ $columns->{'dupe_count'} = {
+ name => '(SELECT COUNT(*) FROM duplicates WHERE duplicates.dupe_of = bugs.bug_id)',
+ title => 'Duplicate Count',
+ };
+}
+
+sub enter_bug_start {
+ my ($self, $args) = @_;
+ # if configured with create_bug_formats, force users into a custom bug
+ # format (can be overridden with a __standard__ format)
+ my $cgi = Bugzilla->cgi;
+ if ($cgi->param('format') && $cgi->param('format') eq '__standard__') {
+ $cgi->delete('format');
+ } elsif (my $format = forced_format($cgi->param('product'))) {
+ $cgi->param('format', $format);
+ }
+}
+
+sub forced_format {
+ # note: this is also called from the guided bug entry extension
+ my ($product) = @_;
+ return undef unless defined $product;
+
+ # check for a forced-format entry
+ my $forced = $create_bug_formats{blessed($product) ? $product->name : $product}
+ || return;
+
+ # should this user be included?
+ my $user = Bugzilla->user;
+ my $include = ref($forced->{include}) ? $forced->{include} : [ $forced->{include} ];
+ foreach my $inc (@$include) {
+ return $forced->{format} if $user->in_group($inc);
+ }
+
+ return undef;
+}
+
+sub query_database {
+ my ($vars) = @_;
+
+ # validate group membership
+ my $user = Bugzilla->user;
+ $user->in_group('query_database')
+ || ThrowUserError('auth_failure', { group => 'query_database',
+ action => 'access',
+ object => 'query_database' });
+
+ # read query
+ my $input = Bugzilla->input_params;
+ my $query = $input->{query};
+ $vars->{query} = $query;
+
+ if ($query) {
+ trick_taint($query);
+ $vars->{executed} = 1;
+
+ # add limit if missing
+ if ($query !~ /\sLIMIT\s+\d+\s*$/si) {
+ $query .= ' LIMIT 1000';
+ $vars->{query} = $query;
+ }
+
+ # log query
+ setlogsock('unix');
+ openlog('apache', 'cons', 'pid', 'local4');
+ syslog('notice', sprintf("[db_query] %s %s", $user->login, $query));
+ closelog();
+
+ # connect to database and execute
+ # switching to the shadow db gives us a read-only connection
+ my $dbh = Bugzilla->switch_to_shadow_db();
+ my $sth;
+ eval {
+ $sth = $dbh->prepare($query);
+ $sth->execute();
+ };
+ if ($@) {
+ $vars->{sql_error} = $@;
+ return;
+ }
+
+ # build result
+ my $columns = $sth->{NAME};
+ my $rows;
+ while (my @row = $sth->fetchrow_array) {
+ push @$rows, \@row;
+ }
+
+ # return results
+ $vars->{columns} = $columns;
+ $vars->{rows} = $rows;
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/BMO/lib/Constants.pm b/extensions/BMO/lib/Constants.pm
new file mode 100644
index 000000000..23eaae9cb
--- /dev/null
+++ b/extensions/BMO/lib/Constants.pm
@@ -0,0 +1,33 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# David Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::BMO::Constants;
+use strict;
+use base qw(Exporter);
+our @EXPORT = qw(
+ REQUEST_MAX_ATTACH_LINES
+);
+
+# Maximum attachment size in lines that will be sent with a
+# requested attachment flag notification.
+use constant REQUEST_MAX_ATTACH_LINES => 1000;
+
+1;
diff --git a/extensions/BMO/lib/Data.pm b/extensions/BMO/lib/Data.pm
new file mode 100644
index 000000000..6ffc4d9ff
--- /dev/null
+++ b/extensions/BMO/lib/Data.pm
@@ -0,0 +1,467 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+# Reed Loden <reed@reedloden.com>
+
+package Bugzilla::Extension::BMO::Data;
+use strict;
+
+use base qw(Exporter);
+use Tie::IxHash;
+
+our @EXPORT = qw( $cf_visible_in_products
+ $cf_flags $cf_project_flags
+ $cf_disabled_flags
+ %group_change_notification
+ $blocking_trusted_setters
+ $blocking_trusted_requesters
+ $status_trusted_wanters
+ $status_trusted_setters
+ $other_setters
+ %always_fileable_group
+ %group_auto_cc
+ %product_sec_groups
+ %create_bug_formats );
+
+# Which custom fields are visible in which products and components.
+#
+# By default, custom fields are visible in all products. However, if the name
+# of the field matches any of these regexps, it is only visible if the
+# product (and component if necessary) is a member of the attached hash. []
+# for component means "all".
+#
+# IxHash keeps them in insertion order, and so we get regexp priorities right.
+our $cf_visible_in_products;
+tie(%$cf_visible_in_products, "Tie::IxHash",
+ qw/^cf_blocking_kilimanjaro|cf_blocking_basecamp|cf_blocking_b2g/ => {
+ "Boot2Gecko" => [],
+ "Core" => [],
+ "Fennec" => [],
+ "Firefox" => [],
+ "Firefox for Android" => [],
+ "Firefox for Metro" => [],
+ "Firefox Health Report" => [],
+ "Marketplace" => [],
+ "mozilla.org" => [],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "NSS" => [],
+ "Socorro" => [],
+ "Testing" => [],
+ "Thunderbird" => [],
+ "Toolkit" => [],
+ "Tracking" => [],
+ "Web Apps" => [],
+ },
+ qr/^cf_blocking_fennec/ => {
+ "addons.mozilla.org" => [],
+ "AUS" => [],
+ "Core" => [],
+ "Fennec" => [],
+ "Firefox for Android" => [],
+ "Firefox Health Report" => [],
+ "Marketing" => ["General"],
+ "Mozilla Localizations" => [],
+ "mozilla.org" => ["Release Engineering", qr/^Release Engineering: /],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "support.mozilla.org" => [],
+ "Tech Evangelism" => [],
+ "Testing" => ["General"],
+ "Toolkit" => [],
+ },
+ qr/^cf_tracking_thunderbird|cf_blocking_thunderbird|cf_status_thunderbird/ => {
+ "support.mozillamessaging.com" => [],
+ "Thunderbird" => [],
+ "MailNews Core" => [],
+ "Mozilla Messaging" => [],
+ "Websites" => ["www.mozillamessaging.com"],
+ },
+ qr/^(cf_(blocking|tracking)_seamonkey|cf_status_seamonkey)/ => {
+ "Composer" => [],
+ "MailNews Core" => [],
+ "Mozilla Localizations" => [],
+ "Other Applications" => [],
+ "SeaMonkey" => [],
+ },
+ qr/^cf_blocking_|cf_tracking_|cf_status/ => {
+ "Add-on SDK" => [],
+ "addons.mozilla.org" => [],
+ "AUS" => [],
+ "Boot2Gecko" => [],
+ "Core" => [],
+ "Core Graveyard" => [],
+ "Directory" => [],
+ "Fennec" => [],
+ "Firefox" => [],
+ "Firefox for Android" => [],
+ "Firefox for Metro" => [],
+ "Firefox Health Report" => [],
+ "MailNews Core" => [],
+ "Mozilla Localizations" => [],
+ "mozilla.org" => ["Release Engineering", qr/^Release Engineering: /],
+ "Mozilla QA" => ["Mozmill Tests"],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "NSS" => [],
+ "Other Applications" => [],
+ "Plugins" => [],
+ "SeaMonkey" => [],
+ "Socorro" => [],
+ "support.mozilla.org" => [],
+ "Tech Evangelism" => [],
+ "Testing" => [],
+ "Toolkit" => [],
+ "Websites" => ["getpersonas.com"],
+ "Webtools" => [],
+ },
+ qr/^cf_colo_site$/ => {
+ "mozilla.org" => [
+ "Server Operations",
+ "Server Operations: DCOps",
+ "Server Operations: Projects",
+ "Server Operations: RelEng",
+ "Server Operations: Security",
+ ],
+ },
+ qw/^cf_office$/ => {
+ "mozilla.org" => ["Server Operations: Desktop Issues"],
+ },
+ qr/^cf_crash_signature$/ => {
+ "Add-on SDK" => [],
+ "addons.mozilla.org" => [],
+ "Boot2Gecko" => [],
+ "Calendar" => [],
+ "Camino" => [],
+ "Composer" => [],
+ "Core" => [],
+ "Directory" => [],
+ "Fennec" => [],
+ "Firefox" => [],
+ "Firefox for Android" => [],
+ "Firefox for Metro" => [],
+ "JSS" => [],
+ "MailNews Core" => [],
+ "Mozilla Labs" => [],
+ "Mozilla Localizations" => [],
+ "mozilla.org" => [],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "NSS" => [],
+ "Other Applications" => [],
+ "Penelope" => [],
+ "Plugins" => [],
+ "Rhino" => [],
+ "SeaMonkey" => [],
+ "Tamarin" => [],
+ "Tech Evangelism" => [],
+ "Testing" => [],
+ "Thunderbird" => [],
+ "Toolkit" => [],
+ },
+ qw/^cf_due_date$/ => {
+ "Mozilla Reps" => [],
+ "mozilla.org" => ["Security Assurance: Review Request"],
+ },
+ qw/^cf_locale$/ => {
+ "www.mozilla.org" => [],
+ },
+);
+
+# Which custom fields are acting as flags (ie. custom flags)
+our $cf_flags = [
+ qr/^cf_(?:blocking|tracking|status)_/,
+];
+
+our $cf_project_flags = [
+ 'cf_blocking_kilimanjaro',
+ 'cf_blocking_b2g',
+ 'cf_blocking_basecamp',
+];
+
+# List of disabled fields.
+# Temp kludge until custom fields can be disabled correctly upstream.
+# Disabled fields are hidden unless they have a value set
+our $cf_disabled_flags = [
+ 'cf_blocking_20',
+ 'cf_status_20',
+ 'cf_blocking_basecamp',
+ 'cf_tracking_firefox5',
+ 'cf_status_firefox5',
+ 'cf_blocking_thunderbird32',
+ 'cf_status_thunderbird32',
+ 'cf_blocking_thunderbird30',
+ 'cf_status_thunderbird30',
+ 'cf_blocking_seamonkey21',
+ 'cf_status_seamonkey21',
+ 'cf_tracking_seamonkey22',
+ 'cf_status_seamonkey22',
+ 'cf_tracking_firefox6',
+ 'cf_status_firefox6',
+ 'cf_tracking_thunderbird6',
+ 'cf_status_thunderbird6',
+ 'cf_tracking_seamonkey23',
+ 'cf_status_seamonkey23',
+ 'cf_tracking_firefox7',
+ 'cf_status_firefox7',
+ 'cf_tracking_thunderbird7',
+ 'cf_status_thunderbird7',
+ 'cf_tracking_seamonkey24',
+ 'cf_status_seamonkey24',
+ 'cf_tracking_firefox8',
+ 'cf_status_firefox8',
+ 'cf_tracking_thunderbird8',
+ 'cf_status_thunderbird8',
+ 'cf_tracking_seamonkey25',
+ 'cf_status_seamonkey25',
+ 'cf_blocking_191',
+ 'cf_status_191',
+ 'cf_blocking_thunderbird33',
+ 'cf_status_thunderbird33',
+ 'cf_tracking_firefox9',
+ 'cf_status_firefox9',
+ 'cf_tracking_thunderbird9',
+ 'cf_status_thunderbird9',
+ 'cf_tracking_seamonkey26',
+ 'cf_status_seamonkey26',
+ 'cf_tracking_firefox10',
+ 'cf_status_firefox10',
+ 'cf_tracking_thunderbird10',
+ 'cf_status_thunderbird10',
+ 'cf_tracking_seamonkey27',
+ 'cf_status_seamonkey27',
+ 'cf_tracking_firefox11',
+ 'cf_status_firefox11',
+ 'cf_tracking_thunderbird11',
+ 'cf_status_thunderbird11',
+ 'cf_tracking_seamonkey28',
+ 'cf_status_seamonkey28',
+ 'cf_tracking_firefox12',
+ 'cf_status_firefox12',
+ 'cf_tracking_thunderbird12',
+ 'cf_status_thunderbird12',
+ 'cf_tracking_seamonkey29',
+ 'cf_status_seamonkey29',
+ 'cf_blocking_192',
+ 'cf_status_192',
+ 'cf_blocking_fennec10',
+ 'cf_tracking_firefox13',
+ 'cf_status_firefox13',
+ 'cf_tracking_thunderbird13',
+ 'cf_status_thunderbird13',
+ 'cf_tracking_seamonkey210',
+ 'cf_status_seamonkey210',
+ 'cf_tracking_firefox14',
+ 'cf_status_firefox14',
+ 'cf_tracking_thunderbird14',
+ 'cf_status_thunderbird14',
+ 'cf_tracking_seamonkey211',
+ 'cf_status_seamonkey211',
+ 'cf_tracking_firefox15',
+ 'cf_status_firefox15',
+ 'cf_tracking_thunderbird15',
+ 'cf_status_thunderbird15',
+ 'cf_tracking_seamonkey212',
+ 'cf_status_seamonkey212',
+ 'cf_tracking_firefox16',
+ 'cf_status_firefox16',
+ 'cf_tracking_thunderbird16',
+ 'cf_status_thunderbird16',
+ 'cf_tracking_seamonkey213',
+ 'cf_status_seamonkey213',
+ 'cf_tracking_firefox17',
+ 'cf_status_firefox17',
+ 'cf_tracking_thunderbird17',
+ 'cf_status_thunderbird17',
+ 'cf_tracking_seamonkey214',
+ 'cf_status_seamonkey214',
+ 'cf_tracking_esr10',
+ 'cf_status_esr10',
+ 'cf_tracking_thunderbird_esr10',
+ 'cf_status_thunderbird_esr10',
+ 'cf_blocking_kilimanjaro',
+ 'cf_tracking_firefox18',
+ 'cf_status_firefox18',
+ 'cf_tracking_thunderbird18',
+ 'cf_status_thunderbird18',
+ 'cf_tracking_seamonkey215',
+ 'cf_status_seamonkey215',
+ 'cf_tracking_firefox19',
+ 'cf_status_firefox19',
+ 'cf_tracking_thunderbird19',
+ 'cf_status_thunderbird19',
+ 'cf_tracking_seamonkey216',
+ 'cf_status_seamonkey216',
+];
+
+# Who to CC on particular bugmails when certain groups are added or removed.
+our %group_change_notification = (
+ 'addons-security' => ['amo-editors@mozilla.org'],
+ 'bugzilla-security' => ['security@bugzilla.org'],
+ 'client-services-security' => ['amo-admins@mozilla.org', 'web-security@mozilla.org'],
+ 'core-security' => ['security@mozilla.org'],
+ 'mozilla-services-security' => ['web-security@mozilla.org'],
+ 'tamarin-security' => ['tamarinsecurity@adobe.com'],
+ 'websites-security' => ['web-security@mozilla.org'],
+ 'webtools-security' => ['web-security@mozilla.org'],
+);
+
+# Only users in certain groups can change certain custom fields in
+# certain ways.
+#
+# Who can set cf_blocking_* or cf_tracking_* to +/-
+our $blocking_trusted_setters = {
+ 'cf_blocking_fennec' => 'fennec-drivers',
+ 'cf_blocking_20' => 'mozilla-next-drivers',
+ qr/^cf_tracking_firefox/ => 'mozilla-next-drivers',
+ qr/^cf_blocking_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_tracking_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_tracking_seamonkey/ => 'seamonkey-council',
+ qr/^cf_blocking_seamonkey/ => 'seamonkey-council',
+ qr/^cf_blocking_kilimanjaro/ => 'kilimanjaro-drivers',
+ qr/^cf_blocking_basecamp/ => 'kilimanjaro-drivers',
+ qr/^cf_tracking_b2g/ => 'kilimanjaro-drivers',
+ qr/^cf_blocking_b2g/ => 'kilimanjaro-drivers',
+ '_default' => 'mozilla-stable-branch-drivers',
+};
+
+# Who can request cf_blocking_* or cf_tracking_*
+our $blocking_trusted_requesters = {
+ qr/^cf_blocking_thunderbird/ => 'thunderbird-trusted-requesters',
+ '_default' => 'everyone',
+};
+
+# Who can set cf_status_* to "wanted"?
+our $status_trusted_wanters = {
+ 'cf_status_20' => 'mozilla-next-drivers',
+ qr/^cf_status_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_status_seamonkey/ => 'seamonkey-council',
+ '_default' => 'mozilla-stable-branch-drivers',
+};
+
+# Who can set cf_status_* to values other than "wanted"?
+our $status_trusted_setters = {
+ qr/^cf_status_thunderbird/ => 'editbugs',
+ '_default' => 'canconfirm',
+};
+
+# Who can set other custom flags (use full field names only, not regex's)
+our $other_setters = {
+ 'cf_colo_site' => ['infra', 'build'],
+};
+
+# Groups in which you can always file a bug, whoever you are.
+our %always_fileable_group = (
+ 'addons-security' => 1,
+ 'bugzilla-security' => 1,
+ 'client-services-security' => 1,
+ 'consulting' => 1,
+ 'core-security' => 1,
+ 'finance' => 1,
+ 'infra' => 1,
+ 'infrasec' => 1,
+ 'l20n-security' => 1,
+ 'marketing-private' => 1,
+ 'mozilla-confidential' => 1,
+ 'mozilla-corporation-confidential' => 1,
+ 'mozilla-foundation-confidential' => 1,
+ 'mozilla-engagement' => 1,
+ 'mozilla-messaging-confidential' => 1,
+ 'partner-confidential' => 1,
+ 'payments-confidential' => 1,
+ 'tamarin-security' => 1,
+ 'websites-security' => 1,
+ 'webtools-security' => 1,
+ 'winqual-data' => 1,
+);
+
+# Mapping of products to their security bits
+our %product_sec_groups = (
+ "addons.mozilla.org" => 'client-services-security',
+ "Android Background Services" => 'mozilla-services-security',
+ "AUS" => 'client-services-security',
+ "Bugzilla" => 'bugzilla-security',
+ "bugzilla.mozilla.org" => 'bugzilla-security',
+ "Community Tools" => 'websites-security',
+ "Developer Documentation" => 'websites-security',
+ "Finance" => 'finance',
+ "Firefox Health Report" => 'mozilla-services-security',
+ "Input" => 'websites-security',
+ "Internet Public Policy" => 'mozilla-corporation-confidential',
+ "L20n" => 'l20n-security',
+ "Legal" => 'legal',
+ "Marketing" => 'marketing-private',
+ "Marketplace" => 'client-services-security',
+ "Mozilla Corporation" => 'mozilla-corporation-confidential',
+ "Mozilla Developer Network" => 'websites-security',
+ "Mozilla Grants" => 'grants',
+ "Mozilla Messaging" => 'mozilla-messaging-confidential',
+ "Mozilla Metrics" => 'metrics-private',
+ "mozilla.org" => 'mozilla-confidential',
+ "Mozilla PR" => 'pr-private',
+ "Mozilla QA" => 'mozilla-corporation-confidential',
+ "Mozilla Reps" => 'mozilla-reps',
+ "Mozilla Services" => 'mozilla-services-security',
+ "mozillaignite" => 'websites-security',
+ "Popcorn" => 'websites-security',
+ "Privacy" => 'privacy',
+ "quality.mozilla.org" => 'websites-security',
+ "Skywriter" => 'websites-security',
+ "Socorro" => 'client-services-security',
+ "Snippets" => 'websites-security',
+ "support.mozilla.org" => 'websites-security',
+ "support.mozillamessaging.com" => 'websites-security',
+ "Talkback" => 'talkback-private',
+ "Tamarin" => 'tamarin-security',
+ "Testopia" => 'bugzilla-security',
+ "Web Apps" => 'client-services-security',
+ "webmaker.org" => 'websites-security',
+ "Thimble" => 'websites-security',
+ "Websites" => 'websites-security',
+ "Webtools" => 'webtools-security',
+ "www.mozilla.org" => 'websites-security',
+ "_default" => 'core-security'
+);
+
+# Automatically CC users to bugs filed into configured groups and products
+our %group_auto_cc = (
+ 'partner-confidential' => {
+ 'Marketing' => ['jbalaco@mozilla.com'],
+ '_default' => ['mbest@mozilla.com'],
+ },
+);
+
+# Default security groups for products should always been fileable
+map { $always_fileable_group{$_} = 1 } values %product_sec_groups;
+
+# Force create-bug template by product
+# Users in 'include' group will be fored into using the form.
+our %create_bug_formats = (
+ 'Mozilla Developer Network' => {
+ 'format' => 'mdn',
+ 'include' => 'everyone',
+ },
+ 'Legal' => {
+ 'format' => 'legal',
+ 'include' => 'everyone',
+ },
+);
+
+1;
diff --git a/extensions/BMO/lib/FakeBug.pm b/extensions/BMO/lib/FakeBug.pm
new file mode 100644
index 000000000..6127cb560
--- /dev/null
+++ b/extensions/BMO/lib/FakeBug.pm
@@ -0,0 +1,42 @@
+package Bugzilla::Extension::BMO::FakeBug;
+
+# hack to allow the bug entry templates to use check_can_change_field to see if
+# various field values should be available to the current user
+
+use strict;
+
+use Bugzilla::Bug;
+
+our $AUTOLOAD;
+
+sub new {
+ my $class = shift;
+ my $self = shift;
+ bless $self, $class;
+ return $self;
+}
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $name = $AUTOLOAD;
+ $name =~ s/.*://;
+ return exists $self->{$name} ? $self->{$name} : undef;
+}
+
+sub check_can_change_field {
+ my $self = shift;
+ return Bugzilla::Bug::check_can_change_field($self, @_)
+}
+
+sub _changes_everconfirmed {
+ my $self = shift;
+ return Bugzilla::Bug::_changes_everconfirmed($self, @_)
+}
+
+sub everconfirmed {
+ my $self = shift;
+ return ($self->{'status'} == 'UNCONFIRMED') ? 0 : 1;
+}
+
+1;
+
diff --git a/extensions/BMO/lib/Reports.pm b/extensions/BMO/lib/Reports.pm
new file mode 100644
index 000000000..0f3a391d9
--- /dev/null
+++ b/extensions/BMO/lib/Reports.pm
@@ -0,0 +1,1191 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::BMO::Reports;
+use strict;
+
+use Bugzilla::Extension::BMO::Data qw($cf_disabled_flags);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Field;
+use Bugzilla::Group;
+use Bugzilla::User;
+use Bugzilla::Util qw(trim detaint_natural trick_taint correct_urlbase);
+
+use Date::Parse;
+use DateTime;
+use JSON qw(-convert_blessed_universally);
+use List::MoreUtils qw(uniq);
+
+use base qw(Exporter);
+
+our @EXPORT = qw( user_activity_report
+ triage_reports
+ group_admins_report
+ email_queue_report
+ release_tracking_report
+ group_membership_report
+ group_members_report );
+
+sub user_activity_report {
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+
+ my @who = ();
+ my $from = trim($input->{'from'} || '');
+ my $to = trim($input->{'to'} || '');
+ my $action = $input->{'action'} || '';
+
+ # fix non-breaking hyphens
+ $from =~ s/\N{U+2011}/-/g;
+ $to =~ s/\N{U+2011}/-/g;
+
+ if ($from eq '') {
+ my $dt = DateTime->now()->subtract('weeks' => 8);
+ $from = $dt->ymd('-');
+ }
+ if ($to eq '') {
+ my $dt = DateTime->now();
+ $to = $dt->ymd('-');
+ }
+
+ if ($action eq 'run') {
+ if ($input->{'who'} eq '') {
+ ThrowUserError('user_activity_missing_username');
+ }
+ Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} });
+
+ my $from_dt = _string_to_datetime($from);
+ $from = $from_dt->ymd();
+
+ my $to_dt = _string_to_datetime($to);
+ $to = $to_dt->ymd();
+ # add one day to include all activity that happened on the 'to' date
+ $to_dt->add(days => 1);
+
+ my ($activity_joins, $activity_where) = ('', '');
+ my ($attachments_joins, $attachments_where) = ('', '');
+ if (Bugzilla->params->{"insidergroup"}
+ && !Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'}))
+ {
+ $activity_joins = "LEFT JOIN attachments
+ ON attachments.attach_id = bugs_activity.attach_id";
+ $activity_where = "AND COALESCE(attachments.isprivate, 0) = 0";
+ $attachments_where = $activity_where;
+ }
+
+ my @who_bits;
+ foreach my $who (
+ ref $input->{'who'}
+ ? @{$input->{'who'}}
+ : $input->{'who'}
+ ) {
+ push @who, $who;
+ push @who_bits, '?';
+ }
+ my $who_bits = join(',', @who_bits);
+
+ if (!@who) {
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+ my $vars = {};
+ $vars->{'script'} = $cgi->url(-relative => 1);
+ $vars->{'fields'} = {};
+ $vars->{'matches'} = [];
+ $vars->{'matchsuccess'} = 0;
+ $vars->{'matchmultiple'} = 1;
+ print $cgi->header();
+ $template->process("global/confirm-user-match.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+
+ $from_dt = $from_dt->ymd() . ' 00:00:00';
+ $to_dt = $to_dt->ymd() . ' 23:59:59';
+ my @params;
+ for (1..4) {
+ push @params, @who;
+ push @params, ($from_dt, $to_dt);
+ }
+
+ my $order = ($input->{'sort'} && $input->{'sort'} eq 'bug')
+ ? 'bug_id, bug_when' : 'bug_when';
+
+ my $comment_filter = '';
+ if (!Bugzilla->user->is_insider) {
+ $comment_filter = 'AND longdescs.isprivate = 0';
+ }
+
+ my $query = "
+ SELECT
+ fielddefs.name,
+ bugs_activity.bug_id,
+ bugs_activity.attach_id,
+ ".$dbh->sql_date_format('bugs_activity.bug_when', '%Y.%m.%d %H:%i:%s')." AS ts,
+ bugs_activity.removed,
+ bugs_activity.added,
+ profiles.login_name,
+ bugs_activity.comment_id,
+ bugs_activity.bug_when
+ FROM bugs_activity
+ $activity_joins
+ LEFT JOIN fielddefs
+ ON bugs_activity.fieldid = fielddefs.id
+ INNER JOIN profiles
+ ON profiles.userid = bugs_activity.who
+ WHERE profiles.login_name IN ($who_bits)
+ AND bugs_activity.bug_when >= ? AND bugs_activity.bug_when <= ?
+ $activity_where
+
+ UNION ALL
+
+ SELECT
+ 'bug_id' AS name,
+ bugs.bug_id,
+ NULL AS attach_id,
+ ".$dbh->sql_date_format('bugs.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ '(new bug)' AS removed,
+ bugs.short_desc AS added,
+ profiles.login_name,
+ NULL AS comment_id,
+ bugs.creation_ts AS bug_when
+ FROM bugs
+ INNER JOIN profiles
+ ON profiles.userid = bugs.reporter
+ WHERE profiles.login_name IN ($who_bits)
+ AND bugs.creation_ts >= ? AND bugs.creation_ts <= ?
+
+ UNION ALL
+
+ SELECT
+ 'longdesc' AS name,
+ longdescs.bug_id,
+ NULL AS attach_id,
+ DATE_FORMAT(longdescs.bug_when, '%Y.%m.%d %H:%i:%s') AS ts,
+ '' AS removed,
+ '' AS added,
+ profiles.login_name,
+ longdescs.comment_id AS comment_id,
+ longdescs.bug_when
+ FROM longdescs
+ INNER JOIN profiles
+ ON profiles.userid = longdescs.who
+ WHERE profiles.login_name IN ($who_bits)
+ AND longdescs.bug_when >= ? AND longdescs.bug_when <= ?
+ $comment_filter
+
+ UNION ALL
+
+ SELECT
+ 'attachments.description' AS name,
+ attachments.bug_id,
+ attachments.attach_id,
+ ".$dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ '(new attachment)' AS removed,
+ attachments.description AS added,
+ profiles.login_name,
+ NULL AS comment_id,
+ attachments.creation_ts AS bug_when
+ FROM attachments
+ INNER JOIN profiles
+ ON profiles.userid = attachments.submitter_id
+ WHERE profiles.login_name IN ($who_bits)
+ AND attachments.creation_ts >= ? AND attachments.creation_ts <= ?
+ $attachments_where
+
+ ORDER BY $order ";
+
+ my $list = $dbh->selectall_arrayref($query, undef, @params);
+
+ if ($input->{debug}) {
+ while (my $param = shift @params) {
+ $query =~ s/\?/$dbh->quote($param)/e;
+ }
+ $vars->{debug_sql} = $query;
+ }
+
+ my @operations;
+ my $operation = {};
+ my $changes = [];
+ my $incomplete_data = 0;
+ my %bug_ids;
+
+ foreach my $entry (@$list) {
+ my ($fieldname, $bugid, $attachid, $when, $removed, $added, $who,
+ $comment_id) = @$entry;
+ my %change;
+ my $activity_visible = 1;
+
+ next unless Bugzilla->user->can_see_bug($bugid);
+
+ # check if the user should see this field's activity
+ if ($fieldname eq 'remaining_time'
+ || $fieldname eq 'estimated_time'
+ || $fieldname eq 'work_time'
+ || $fieldname eq 'deadline')
+ {
+ $activity_visible = Bugzilla->user->is_timetracker;
+ }
+ elsif ($fieldname eq 'longdescs.isprivate'
+ && !Bugzilla->user->is_insider
+ && $added)
+ {
+ $activity_visible = 0;
+ }
+ else {
+ $activity_visible = 1;
+ }
+
+ if ($activity_visible) {
+ # Check for the results of an old Bugzilla data corruption bug
+ if (($added eq '?' && $removed eq '?')
+ || ($added =~ /^\? / || $removed =~ /^\? /)) {
+ $incomplete_data = 1;
+ }
+
+ # Start a new changeset if required (depends on the sort order)
+ my $is_new_changeset;
+ if ($order eq 'bug_when') {
+ $is_new_changeset =
+ $operation->{'who'} &&
+ (
+ $who ne $operation->{'who'}
+ || $when ne $operation->{'when'}
+ || $bugid != $operation->{'bug'}
+ );
+ } else {
+ $is_new_changeset =
+ $operation->{'bug'} &&
+ $bugid != $operation->{'bug'};
+ }
+ if ($is_new_changeset) {
+ $operation->{'changes'} = $changes;
+ push (@operations, $operation);
+ $operation = {};
+ $changes = [];
+ }
+
+ $bug_ids{$bugid} = 1;
+
+ $operation->{'bug'} = $bugid;
+ $operation->{'who'} = $who;
+ $operation->{'when'} = $when;
+
+ $change{'fieldname'} = $fieldname;
+ $change{'attachid'} = $attachid;
+ $change{'removed'} = $removed;
+ $change{'added'} = $added;
+ $change{'when'} = $when;
+
+ if ($comment_id) {
+ $change{'comment'} = Bugzilla::Comment->new($comment_id);
+ next if $change{'comment'}->count == 0;
+ }
+
+ if ($attachid) {
+ $change{'attach'} = Bugzilla::Attachment->new($attachid);
+ }
+
+ push (@$changes, \%change);
+ }
+ }
+
+ if ($operation->{'who'}) {
+ $operation->{'changes'} = $changes;
+ push (@operations, $operation);
+ }
+
+ $vars->{'incomplete_data'} = $incomplete_data;
+ $vars->{'operations'} = \@operations;
+
+ my @bug_ids = sort { $a <=> $b } keys %bug_ids;
+ $vars->{'bug_ids'} = \@bug_ids;
+ }
+
+ $vars->{'action'} = $action;
+ $vars->{'who'} = join(',', @who);
+ $vars->{'who_count'} = scalar @who;
+ $vars->{'from'} = $from;
+ $vars->{'to'} = $to;
+ $vars->{'sort'} = $input->{'sort'};
+}
+
+sub _string_to_datetime {
+ my $input = shift;
+ my $time = _parse_date($input)
+ or ThrowUserError('report_invalid_date', { date => $input });
+ return _time_to_datetime($time);
+}
+
+sub _time_to_datetime {
+ my $time = shift;
+ return DateTime->from_epoch(epoch => $time)
+ ->set_time_zone('local')
+ ->truncate(to => 'day');
+}
+
+sub _parse_date {
+ my ($str) = @_;
+ if ($str =~ /^(-|\+)?(\d+)([hHdDwWmMyY])$/) {
+ # relative date
+ my ($sign, $amount, $unit, $date) = ($1, $2, lc $3, time);
+ my ($sec, $min, $hour, $mday, $month, $year, $wday) = localtime($date);
+ $amount = -$amount if $sign && $sign eq '+';
+ if ($unit eq 'w') {
+ # convert weeks to days
+ $amount = 7*$amount + $wday;
+ $unit = 'd';
+ }
+ if ($unit eq 'd') {
+ $date -= $sec + 60*$min + 3600*$hour + 24*3600*$amount;
+ return $date;
+ }
+ elsif ($unit eq 'y') {
+ return str2time(sprintf("%4d-01-01 00:00:00", $year+1900-$amount));
+ }
+ elsif ($unit eq 'm') {
+ $month -= $amount;
+ while ($month<0) { $year--; $month += 12; }
+ return str2time(sprintf("%4d-%02d-01 00:00:00", $year+1900, $month+1));
+ }
+ elsif ($unit eq 'h') {
+ # Special case 0h for 'beginning of this hour'
+ if ($amount == 0) {
+ $date -= $sec + 60*$min;
+ } else {
+ $date -= 3600*$amount;
+ }
+ return $date;
+ }
+ return undef;
+ }
+ return str2time($str);
+}
+
+sub triage_reports {
+ my ($vars, $filter) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ if (exists $input->{'action'} && $input->{'action'} eq 'run' && $input->{'product'}) {
+
+ # load product and components from input
+
+ my $product = Bugzilla::Product->new({ name => $input->{'product'} })
+ || ThrowUserError('invalid_object', { object => 'Product', value => $input->{'product'} });
+
+ my @component_ids;
+ if ($input->{'component'} ne '') {
+ my $ra_components = ref($input->{'component'})
+ ? $input->{'component'} : [ $input->{'component'} ];
+ foreach my $component_name (@$ra_components) {
+ my $component = Bugzilla::Component->new({ name => $component_name, product => $product })
+ || ThrowUserError('invalid_object', { object => 'Component', value => $component_name });
+ push @component_ids, $component->id;
+ }
+ }
+
+ # determine which comment filters to run
+
+ my $filter_commenter = $input->{'filter_commenter'};
+ my $filter_commenter_on = $input->{'commenter'};
+ my $filter_last = $input->{'filter_last'};
+ my $filter_last_period = $input->{'last'};
+
+ if (!$filter_commenter || $filter_last) {
+ $filter_commenter = '1';
+ $filter_commenter_on = 'reporter';
+ }
+
+ my $filter_commenter_id;
+ if ($filter_commenter && $filter_commenter_on eq 'is') {
+ Bugzilla::User::match_field({ 'commenter_is' => {'type' => 'single'} });
+ my $user = Bugzilla::User->new({ name => $input->{'commenter_is'} })
+ || ThrowUserError('invalid_object', { object => 'User', value => $input->{'commenter_is'} });
+ $filter_commenter_id = $user ? $user->id : 0;
+ }
+
+ my $filter_last_time;
+ if ($filter_last) {
+ if ($filter_last_period eq 'is') {
+ $filter_last_period = -1;
+ $filter_last_time = str2time($input->{'last_is'} . " 00:00:00") || 0;
+ } else {
+ detaint_natural($filter_last_period);
+ $filter_last_period = 14 if $filter_last_period < 14;
+ }
+ }
+
+ # form sql queries
+
+ my $now = (time);
+ my $bugs_sql = "
+ SELECT bug_id, short_desc, reporter, creation_ts
+ FROM bugs
+ WHERE product_id = ?
+ AND bug_status = 'UNCONFIRMED'";
+ if (@component_ids) {
+ $bugs_sql .= " AND component_id IN (" . join(',', @component_ids) . ")";
+ }
+ $bugs_sql .= "
+ ORDER BY creation_ts
+ ";
+
+ my $comment_count_sql = "
+ SELECT COUNT(*)
+ FROM longdescs
+ WHERE bug_id = ?
+ ";
+
+ my $comment_sql = "
+ SELECT who, bug_when, type, thetext, extra_data
+ FROM longdescs
+ WHERE bug_id = ?
+ ";
+ if (!Bugzilla->user->is_insider) {
+ $comment_sql .= " AND isprivate = 0 ";
+ }
+ $comment_sql .= "
+ ORDER BY bug_when DESC
+ LIMIT 1
+ ";
+
+ my $attach_sql = "
+ SELECT description, isprivate
+ FROM attachments
+ WHERE attach_id = ?
+ ";
+
+ # work on an initial list of bugs
+
+ my $list = $dbh->selectall_arrayref($bugs_sql, undef, $product->id);
+ my @bugs;
+
+ foreach my $entry (@$list) {
+ my ($bug_id, $summary, $reporter_id, $creation_ts) = @$entry;
+
+ next unless $user->can_see_bug($bug_id);
+
+ # get last comment information
+
+ my ($comment_count) = $dbh->selectrow_array($comment_count_sql, undef, $bug_id);
+ my ($commenter_id, $comment_ts, $type, $comment, $extra)
+ = $dbh->selectrow_array($comment_sql, undef, $bug_id);
+ my $commenter = 0;
+
+ # apply selected filters
+
+ if ($filter_commenter) {
+ next if $comment_count <= 1;
+
+ if ($filter_commenter_on eq 'reporter') {
+ next if $commenter_id != $reporter_id;
+
+ } elsif ($filter_commenter_on eq 'noconfirm') {
+ $commenter = Bugzilla::User->new($commenter_id);
+ next if $commenter_id != $reporter_id
+ || $commenter->in_group('canconfirm');
+
+ } elsif ($filter_commenter_on eq 'is') {
+ next if $commenter_id != $filter_commenter_id;
+ }
+ } else {
+ $input->{'commenter'} = '';
+ $input->{'commenter_is'} = '';
+ }
+
+ if ($filter_last) {
+ my $comment_time = str2time($comment_ts)
+ or next;
+ if ($filter_last_period == -1) {
+ next if $comment_time >= $filter_last_time;
+ } else {
+ next if $now - $comment_time <= 60 * 60 * 24 * $filter_last_period;
+ }
+ } else {
+ $input->{'last'} = '';
+ $input->{'last_is'} = '';
+ }
+
+ # get data for attachment comments
+
+ if ($comment eq '' && $type == CMT_ATTACHMENT_CREATED) {
+ my ($description, $is_private) = $dbh->selectrow_array($attach_sql, undef, $extra);
+ next if $is_private && !Bugzilla->user->is_insider;
+ $comment = "(Attachment) " . $description;
+ }
+
+ # truncate long comments
+
+ if (length($comment) > 80) {
+ $comment = substr($comment, 0, 80) . '...';
+ }
+
+ # build bug hash for template
+
+ my $bug = {};
+ $bug->{id} = $bug_id;
+ $bug->{summary} = $summary;
+ $bug->{reporter} = Bugzilla::User->new($reporter_id);
+ $bug->{creation_ts} = $creation_ts;
+ $bug->{commenter} = $commenter || Bugzilla::User->new($commenter_id);
+ $bug->{comment_ts} = $comment_ts;
+ $bug->{comment} = $comment;
+ $bug->{comment_count} = $comment_count;
+ push @bugs, $bug;
+ }
+
+ @bugs = sort { $b->{comment_ts} cmp $a->{comment_ts} } @bugs;
+
+ $vars->{bugs} = \@bugs;
+ } else {
+ $input->{action} = '';
+ }
+
+ if (!$input->{filter_commenter} && !$input->{filter_last}) {
+ $input->{filter_commenter} = 1;
+ }
+
+ $vars->{'input'} = $input;
+}
+
+sub group_admins_report {
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+
+ ($user->in_group('editusers') || $user->in_group('infrasec'))
+ || ThrowUserError('auth_failure', { group => 'editusers',
+ action => 'run',
+ object => 'group_admins' });
+
+ my $query = "
+ SELECT groups.name, " .
+ $dbh->sql_group_concat('profiles.login_name', "','", 1) . "
+ FROM groups
+ LEFT JOIN user_group_map
+ ON user_group_map.group_id = groups.id
+ AND user_group_map.isbless = 1
+ AND user_group_map.grant_type = 0
+ LEFT JOIN profiles
+ ON user_group_map.user_id = profiles.userid
+ WHERE groups.isbuggroup = 1
+ GROUP BY groups.name";
+
+ my @groups;
+ foreach my $group (@{ $dbh->selectall_arrayref($query) }) {
+ my @admins;
+ if ($group->[1]) {
+ foreach my $admin (split(/,/, $group->[1])) {
+ push(@admins, Bugzilla::User->new({ name => $admin }));
+ }
+ }
+ push(@groups, { name => $group->[0], admins => \@admins });
+ }
+
+ $vars->{'groups'} = \@groups;
+}
+
+sub group_membership_report {
+ my ($page, $vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $cgi = Bugzilla->cgi;
+
+ ($user->in_group('editusers') || $user->in_group('infrasec'))
+ || ThrowUserError('auth_failure', { group => 'editusers',
+ action => 'run',
+ object => 'group_admins' });
+
+ my $who = $cgi->param('who');
+ if (!defined($who) || $who eq '') {
+ if ($page eq 'group_membership.txt') {
+ print $cgi->redirect("page.cgi?id=group_membership.html&output=txt");
+ exit;
+ }
+ $vars->{'output'} = $cgi->param('output');
+ return;
+ }
+
+ Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} });
+ $who = Bugzilla->input_params->{'who'};
+ $who = ref($who) ? $who : [ $who ];
+
+ my @users;
+ foreach my $login (@$who) {
+ my $u = Bugzilla::User->new(login_to_id($login, 1));
+
+ # this is lifted from $user->groups()
+ # we need to show which groups are direct and which are inherited
+
+ my $groups_to_check = $dbh->selectcol_arrayref(
+ q{SELECT DISTINCT group_id
+ FROM user_group_map
+ WHERE user_id = ? AND isbless = 0}, undef, $u->id);
+
+ my $rows = $dbh->selectall_arrayref(
+ "SELECT DISTINCT grantor_id, member_id
+ FROM group_group_map
+ WHERE grant_type = " . GROUP_MEMBERSHIP);
+
+ my %group_membership;
+ foreach my $row (@$rows) {
+ my ($grantor_id, $member_id) = @$row;
+ push (@{ $group_membership{$member_id} }, $grantor_id);
+ }
+
+ my %checked_groups;
+ my %direct_groups;
+ my %indirect_groups;
+ my %groups;
+
+ foreach my $member_id (@$groups_to_check) {
+ $direct_groups{$member_id} = 1;
+ }
+
+ while (scalar(@$groups_to_check) > 0) {
+ my $member_id = shift @$groups_to_check;
+ if (!$checked_groups{$member_id}) {
+ $checked_groups{$member_id} = 1;
+ my $members = $group_membership{$member_id};
+ my @new_to_check = grep(!$checked_groups{$_}, @$members);
+ push(@$groups_to_check, @new_to_check);
+ foreach my $id (@new_to_check) {
+ $indirect_groups{$id} = $member_id;
+ }
+ $groups{$member_id} = 1;
+ }
+ }
+
+ my @groups;
+ my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]);
+ foreach my $group (@$ra_groups) {
+ my $via;
+ if ($direct_groups{$group->id}) {
+ $via = '';
+ } else {
+ foreach my $g (@$ra_groups) {
+ if ($g->id == $indirect_groups{$group->id}) {
+ $via = $g->name;
+ last;
+ }
+ }
+ }
+ push @groups, {
+ name => $group->name,
+ desc => $group->description,
+ via => $via,
+ };
+ }
+
+ push @users, {
+ user => $u,
+ groups => \@groups,
+ };
+ }
+
+ $vars->{'who'} = $who;
+ $vars->{'users'} = \@users;
+}
+
+sub group_members_report {
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $cgi = Bugzilla->cgi;
+
+ ($user->in_group('editusers') || $user->in_group('infrasec'))
+ || ThrowUserError('auth_failure', { group => 'editusers',
+ action => 'run',
+ object => 'group_admins' });
+
+ my $include_disabled = $cgi->param('include_disabled') ? 1 : 0;
+ $vars->{'include_disabled'} = $include_disabled;
+
+ # don't allow all groups, to avoid putting pain on the servers
+ my @group_names =
+ sort
+ grep { !/^(?:bz_.+|canconfirm|editbugs|everyone)$/ }
+ map { lc($_->name) }
+ Bugzilla::Group->get_all;
+ unshift(@group_names, '');
+ $vars->{'groups'} = \@group_names;
+
+ # load selected group
+ my $group = lc(trim($cgi->param('group') || ''));
+ $group = '' unless grep { $_ eq $group } @group_names;
+ return if $group eq '';
+ my $group_obj = Bugzilla::Group->new({ name => $group });
+ $vars->{'group'} = $group;
+
+ # direct members
+ my @types = (
+ {
+ name => 'direct',
+ members => _filter_userlist($group_obj->members_direct, $include_disabled),
+ },
+ );
+
+ # indirect members, by group
+ foreach my $member_group (sort @{ $group_obj->grant_direct(GROUP_MEMBERSHIP) }) {
+ push @types, {
+ name => $member_group->name,
+ members => _filter_userlist($member_group->members_direct, $include_disabled),
+ },
+ }
+
+ # make it easy for the template to detect an empty group
+ my $has_members = 0;
+ foreach my $type (@types) {
+ $has_members += scalar(@{ $type->{members} });
+ last if $has_members;
+ }
+ @types = () unless $has_members;
+
+ if (@types) {
+ # add last-login
+ my $user_ids = join(',', map { map { $_->id } @{ $_->{members} } } @types);
+ my $tokens = $dbh->selectall_hashref("
+ SELECT profiles.userid,
+ (SELECT DATEDIFF(curdate(), logincookies.lastused) lastseen
+ FROM logincookies
+ WHERE logincookies.userid = profiles.userid
+ ORDER BY lastused DESC
+ LIMIT 1) lastseen
+ FROM profiles
+ WHERE userid IN ($user_ids)",
+ 'userid');
+ foreach my $type (@types) {
+ foreach my $member (@{ $type->{members} }) {
+ $member->{lastseen} =
+ defined $tokens->{$member->id}->{lastseen}
+ ? $tokens->{$member->id}->{lastseen}
+ : '>' . MAX_LOGINCOOKIE_AGE;
+ }
+ }
+ }
+
+ $vars->{'types'} = \@types;
+}
+
+sub _filter_userlist {
+ my ($list, $include_disabled) = @_;
+ $list = [ grep { $_->is_enabled } @$list ] unless $include_disabled;
+ return [ sort { lc($a->identity) cmp lc($b->identity) } @$list ];
+}
+
+sub email_queue_report {
+ my ($vars, $filter) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+
+ $user->in_group('admin') || $user->in_group('infra')
+ || ThrowUserError('auth_failure', { group => 'admin',
+ action => 'run',
+ object => 'email_queue' });
+
+ my $query = "
+ SELECT j.jobid,
+ j.insert_time,
+ j.run_after AS run_time,
+ COUNT(e.jobid) AS error_count,
+ MAX(e.error_time) AS error_time,
+ e.message AS error_message
+ FROM ts_job j
+ LEFT JOIN ts_error e ON e.jobid = j.jobid
+ GROUP BY j.jobid
+ ORDER BY j.run_after";
+
+ $vars->{'jobs'} = $dbh->selectall_arrayref($query, { Slice => {} });
+ $vars->{'now'} = (time);
+}
+
+sub release_tracking_report {
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ my @flag_names = qw(
+ approval-mozilla-release
+ approval-mozilla-beta
+ approval-mozilla-aurora
+ approval-mozilla-central
+ approval-comm-release
+ approval-comm-beta
+ approval-comm-aurora
+ approval-calendar-release
+ approval-calendar-beta
+ approval-calendar-aurora
+ approval-mozilla-esr10
+ );
+
+ my @flags_json;
+ my @fields_json;
+ my @products_json;
+
+ #
+ # tracking flags
+ #
+
+ my $all_products = $user->get_selectable_products;
+ my @usable_products;
+
+ # build list of flags and their matching products
+
+ my @invalid_flag_names;
+ foreach my $flag_name (@flag_names) {
+ # grab all matching flag_types
+ my @flag_types = @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })};
+
+ # remove invalid flags
+ if (!@flag_types) {
+ push @invalid_flag_names, $flag_name;
+ next;
+ }
+
+ # we need a list of products, based on inclusions/exclusions
+ my @products;
+ my %flag_types;
+ foreach my $flag_type (@flag_types) {
+ $flag_types{$flag_type->name} = $flag_type->id;
+ my $has_all = 0;
+ my @exclusion_ids;
+ my @inclusion_ids;
+ foreach my $flag_type (@flag_types) {
+ if (scalar keys %{$flag_type->inclusions}) {
+ my $inclusions = $flag_type->inclusions;
+ foreach my $key (keys %$inclusions) {
+ push @inclusion_ids, ($inclusions->{$key} =~ /^(\d+)/);
+ }
+ } elsif (scalar keys %{$flag_type->exclusions}) {
+ my $exclusions = $flag_type->exclusions;
+ foreach my $key (keys %$exclusions) {
+ push @exclusion_ids, ($exclusions->{$key} =~ /^(\d+)/);
+ }
+ } else {
+ $has_all = 1;
+ last;
+ }
+ }
+
+ if ($has_all) {
+ push @products, @$all_products;
+ } elsif (scalar @exclusion_ids) {
+ push @products, @$all_products;
+ foreach my $exclude_id (uniq @exclusion_ids) {
+ @products = grep { $_->id != $exclude_id } @products;
+ }
+ } else {
+ foreach my $include_id (uniq @inclusion_ids) {
+ push @products, grep { $_->id == $include_id } @$all_products;
+ }
+ }
+ }
+ @products = uniq @products;
+ push @usable_products, @products;
+ my @product_ids = map { $_->id } sort { lc($a->name) cmp lc($b->name) } @products;
+
+ push @flags_json, {
+ name => $flag_name,
+ id => $flag_types{$flag_name} || 0,
+ products => \@product_ids,
+ fields => [],
+ };
+ }
+ foreach my $flag_name (@invalid_flag_names) {
+ @flag_names = grep { $_ ne $flag_name } @flag_names;
+ }
+ @usable_products = uniq @usable_products;
+
+ # build a list of tracking flags for each product
+ # also build the list of all fields
+
+ my @unlink_products;
+ foreach my $product (@usable_products) {
+ my @fields =
+ grep { _is_active_status_field($_->name) }
+ Bugzilla->active_custom_fields({ product => $product });
+ my @field_ids = map { $_->id } @fields;
+ if (!scalar @fields) {
+ push @unlink_products, $product;
+ next;
+ }
+
+ # product
+ push @products_json, {
+ name => $product->name,
+ id => $product->id,
+ fields => \@field_ids,
+ };
+
+ # add fields to flags
+ foreach my $rh (@flags_json) {
+ if (grep { $_ eq $product->id } @{$rh->{products}}) {
+ push @{$rh->{fields}}, @field_ids;
+ }
+ }
+
+ # add fields to fields_json
+ foreach my $field (@fields) {
+ my $existing = 0;
+ foreach my $rh (@fields_json) {
+ if ($rh->{id} == $field->id) {
+ $existing = 1;
+ last;
+ }
+ }
+ if (!$existing) {
+ push @fields_json, {
+ name => $field->name,
+ id => $field->id,
+ };
+ }
+ }
+ }
+ foreach my $rh (@flags_json) {
+ my @fields = uniq @{$rh->{fields}};
+ $rh->{fields} = \@fields;
+ }
+
+ # remove products which aren't linked with status fields
+
+ foreach my $rh (@flags_json) {
+ my @product_ids;
+ foreach my $id (@{$rh->{products}}) {
+ unless (grep { $_->id == $id } @unlink_products) {
+ push @product_ids, $id;
+ }
+ $rh->{products} = \@product_ids;
+ }
+ }
+
+ #
+ # rapid release dates
+ #
+
+ my @ranges;
+ my $start_date = _string_to_datetime('2011-08-16');
+ my $end_date = $start_date->clone->add(weeks => 6)->add(days => -1);
+ my $now_date = _string_to_datetime('2012-11-19');
+
+ while ($start_date <= $now_date) {
+ unshift @ranges, {
+ value => sprintf("%s-%s", $start_date->ymd(''), $end_date->ymd('')),
+ label => sprintf("%s and %s", $start_date->ymd('-'), $end_date->ymd('-')),
+ };
+
+ $start_date = $end_date->clone;;
+ $start_date->add(days => 1);
+ $end_date->add(weeks => 6);
+ }
+
+ # 2012-11-20 - 2013-01-06 was a 7 week release cycle instead of 6
+ $start_date = _string_to_datetime('2012-11-20');
+ $end_date = $start_date->clone->add(weeks => 7)->add(days => -1);
+ unshift @ranges, {
+ value => sprintf("%s-%s", $start_date->ymd(''), $end_date->ymd('')),
+ label => sprintf("%s and %s", $start_date->ymd('-'), $end_date->ymd('-')),
+ };
+
+ # Back on track with 6 week releases
+ $start_date = _string_to_datetime('2013-01-08');
+ $end_date = $start_date->clone->add(weeks => 6)->add(days => -1);
+ $now_date = _time_to_datetime((time));
+
+ while ($start_date <= $now_date) {
+ unshift @ranges, {
+ value => sprintf("%s-%s", $start_date->ymd(''), $end_date->ymd('')),
+ label => sprintf("%s and %s", $start_date->ymd('-'), $end_date->ymd('-')),
+ };
+
+ $start_date = $end_date->clone;;
+ $start_date->add(days => 1);
+ $end_date->add(weeks => 6);
+ }
+
+ push @ranges, {
+ value => '*',
+ label => 'Anytime',
+ };
+
+ #
+ # run report
+ #
+
+ if ($input->{q} && !$input->{edit}) {
+ my $q = _parse_query($input->{q});
+
+ my @where;
+ my @params;
+ my $query = "
+ SELECT DISTINCT b.bug_id
+ FROM bugs b
+ INNER JOIN flags f ON f.bug_id = b.bug_id ";
+
+ if ($q->{start_date}) {
+ $query .= "INNER JOIN bugs_activity a ON a.bug_id = b.bug_id ";
+ }
+
+ $query .= "WHERE ";
+
+ if ($q->{start_date}) {
+ push @where, "(a.fieldid = ?)";
+ push @params, $q->{field_id};
+
+ push @where, "(a.bug_when >= ?)";
+ push @params, $q->{start_date} . ' 00:00:00';
+ push @where, "(a.bug_when < ?)";
+ push @params, $q->{end_date} . ' 00:00:00';
+
+ push @where, "(a.added LIKE ?)";
+ push @params, '%' . $q->{flag_name} . $q->{flag_status} . '%';
+ }
+
+ push @where, "(f.type_id IN (SELECT id FROM flagtypes WHERE name = ?))";
+ push @params, $q->{flag_name};
+
+ push @where, "(f.status = ?)";
+ push @params, $q->{flag_status};
+
+ if ($q->{product_id}) {
+ push @where, "(b.product_id = ?)";
+ push @params, $q->{product_id};
+ }
+
+ if (scalar @{$q->{fields}}) {
+ my @fields;
+ foreach my $field (@{$q->{fields}}) {
+ push @fields,
+ "(" .
+ ($field->{value} eq '+' ? '' : '!') .
+ "(b.".$field->{name}." IN ('fixed','verified'))" .
+ ") ";
+ }
+ my $join = uc $q->{join};
+ push @where, '(' . join(" $join ", @fields) . ')';
+ }
+
+ $query .= join("\nAND ", @where);
+
+ if ($input->{debug}) {
+ print "Content-Type: text/plain\n\n";
+ $query =~ s/\?/\000/g;
+ foreach my $param (@params) {
+ $query =~ s/\000/$param/;
+ }
+ print "$query\n";
+ exit;
+ }
+
+ my $bugs = $dbh->selectcol_arrayref($query, undef, @params);
+ push @$bugs, 0 unless @$bugs;
+
+ my $urlbase = correct_urlbase();
+ my $cgi = Bugzilla->cgi;
+ print $cgi->redirect(
+ -url => "${urlbase}buglist.cgi?bug_id=" . join(',', @$bugs)
+ );
+ exit;
+ }
+
+ #
+ # set template vars
+ #
+
+ my $json = JSON->new();
+ if (0) {
+ # debugging
+ $json->shrink(0);
+ $json->canonical(1);
+ $vars->{flags_json} = $json->pretty->encode(\@flags_json);
+ $vars->{products_json} = $json->pretty->encode(\@products_json);
+ $vars->{fields_json} = $json->pretty->encode(\@fields_json);
+ } else {
+ $json->shrink(1);
+ $vars->{flags_json} = $json->encode(\@flags_json);
+ $vars->{products_json} = $json->encode(\@products_json);
+ $vars->{fields_json} = $json->encode(\@fields_json);
+ }
+
+ $vars->{flag_names} = \@flag_names;
+ $vars->{ranges} = \@ranges;
+ $vars->{default_query} = $input->{q};
+ foreach my $field (qw(product flags range)) {
+ $vars->{$field} = $input->{$field};
+ }
+}
+
+sub _parse_query {
+ my $q = shift;
+ my @query = split(/:/, $q);
+ my $query;
+
+ # field_id for flag changes
+ $query->{field_id} = get_field_id('flagtypes.name');
+
+ # flag_name
+ my $flag_name = shift @query;
+ @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })}
+ or ThrowUserError('report_invalid_parameter', { name => 'flag_name' });
+ trick_taint($flag_name);
+ $query->{flag_name} = $flag_name;
+
+ # flag_status
+ my $flag_status = shift @query;
+ $flag_status =~ /^([\?\-\+])$/
+ or ThrowUserError('report_invalid_parameter', { name => 'flag_status' });
+ $query->{flag_status} = $1;
+
+ # date_range -> from_ymd to_ymd
+ my $date_range = shift @query;
+ if ($date_range ne '*') {
+ $date_range =~ /^(\d\d\d\d)(\d\d)(\d\d)-(\d\d\d\d)(\d\d)(\d\d)$/
+ or ThrowUserError('report_invalid_parameter', { name => 'date_range' });
+ $query->{start_date} = "$1-$2-$3";
+ $query->{end_date} = "$4-$5-$6";
+ }
+
+ # product_id
+ my $product_id = shift @query;
+ $product_id =~ /^(\d+)$/
+ or ThrowUserError('report_invalid_parameter', { name => 'product_id' });
+ $query->{product_id} = $1;
+
+ # join
+ my $join = shift @query;
+ $join =~ /^(and|or)$/
+ or ThrowUserError('report_invalid_parameter', { name => 'join' });
+ $query->{join} = $1;
+
+ # fields
+ my @fields;
+ foreach my $field (@query) {
+ $field =~ /^(\d+)([\-\+])$/
+ or ThrowUserError('report_invalid_parameter', { name => 'fields' });
+ my ($id, $value) = ($1, $2);
+ my $field_obj = Bugzilla::Field->new($id)
+ or ThrowUserError('report_invalid_parameter', { name => 'field_id' });
+ push @fields, { id => $id, value => $value, name => $field_obj->name };
+ }
+ $query->{fields} = \@fields;
+
+ return $query;
+}
+
+sub _is_active_status_field {
+ my ($field_name) = @_;
+ if ($field_name =~ /^cf_status/) {
+ return !grep { $field_name eq $_ } @$cf_disabled_flags
+ }
+ return 0;
+}
+
+1;
diff --git a/extensions/BMO/lib/WebService.pm b/extensions/BMO/lib/WebService.pm
new file mode 100644
index 000000000..cefcde2f6
--- /dev/null
+++ b/extensions/BMO/lib/WebService.pm
@@ -0,0 +1,208 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+# the specific language governing rights and limitations under the License.
+#
+# The Original Code is the BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation. Portions created
+# by the Initial Developer are Copyright (C) 2011 the Mozilla Foundation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Dave Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::BMO::WebService;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::WebService);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Util qw(detaint_natural trick_taint);
+use Bugzilla::WebService::Util qw(validate);
+use Bugzilla::Field;
+
+sub getBugsConfirmer {
+ my ($self, $params) = validate(@_, 'names');
+ my $dbh = Bugzilla->dbh;
+
+ defined($params->{names})
+ || ThrowCodeError('params_required',
+ { function => 'BMO.getBugsConfirmer', params => ['names'] });
+
+ my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} };
+
+ # start filtering to remove duplicate user ids
+ @user_objects = values %{{ map { $_->id => $_ } @user_objects }};
+
+ my $fieldid = get_field_id('bug_status');
+
+ my $query = "SELECT DISTINCT bugs_activity.bug_id
+ FROM bugs_activity
+ LEFT JOIN bug_group_map
+ ON bugs_activity.bug_id = bug_group_map.bug_id
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.added = 'NEW'
+ AND bugs_activity.removed = 'UNCONFIRMED'
+ AND bugs_activity.who = ?
+ AND bug_group_map.bug_id IS NULL
+ ORDER BY bugs_activity.bug_id";
+
+ my %users;
+ foreach my $user (@user_objects) {
+ my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id);
+ $users{$user->login} = $bugs;
+ }
+
+ return \%users;
+}
+
+sub getBugsVerifier {
+ my ($self, $params) = validate(@_, 'names');
+ my $dbh = Bugzilla->dbh;
+
+ defined($params->{names})
+ || ThrowCodeError('params_required',
+ { function => 'BMO.getBugsVerifier', params => ['names'] });
+
+ my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} };
+
+ # start filtering to remove duplicate user ids
+ @user_objects = values %{{ map { $_->id => $_ } @user_objects }};
+
+ my $fieldid = get_field_id('bug_status');
+
+ my $query = "SELECT DISTINCT bugs_activity.bug_id
+ FROM bugs_activity
+ LEFT JOIN bug_group_map
+ ON bugs_activity.bug_id = bug_group_map.bug_id
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.removed = 'RESOLVED'
+ AND bugs_activity.added = 'VERIFIED'
+ AND bugs_activity.who = ?
+ AND bug_group_map.bug_id IS NULL
+ ORDER BY bugs_activity.bug_id";
+
+ my %users;
+ foreach my $user (@user_objects) {
+ my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id);
+ $users{$user->login} = $bugs;
+ }
+
+ return \%users;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Extension::BMO::Webservice - The BMO WebServices API
+
+=head1 DESCRIPTION
+
+This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+
+=head1 METHODS
+
+See L<Bugzilla::WebService> for a description of how parameters are passed,
+and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
+
+=head2 getBugsConfirmer
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+This method returns public bug ids that a given user has confirmed (changed from
+C<UNCONFIRMED> to C<NEW>).
+
+=item B<Params>
+
+You pass a field called C<names> that is a list of Bugzilla login names to find bugs for.
+
+=over
+
+=item C<names> (array) - An array of strings representing Bugzilla login names.
+
+=back
+
+=item B<Returns>
+
+=over
+
+A hash of Bugzilla login names. Each name points to an array of bug ids that the user has confirmed.
+
+=back
+
+=item B<Errors>
+
+=over
+
+=back
+
+=item B<History>
+
+=over
+
+=item Added in BMO Bugzilla B<4.0>.
+
+=back
+
+=back
+
+=head2 getBugsVerifier
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+This method returns public bug ids that a given user has verified (changed from
+C<RESOLVED> to C<VERIFIED>).
+
+=item B<Params>
+
+You pass a field called C<names> that is a list of Bugzilla login names to find bugs for.
+
+=over
+
+=item C<names> (array) - An array of strings representing Bugzilla login names.
+
+=back
+
+=item B<Returns>
+
+=over
+
+A hash of Bugzilla login names. Each name points to an array of bug ids that the user has verified.
+
+=back
+
+=item B<Errors>
+
+=over
+
+=back
+
+=item B<History>
+
+=over
+
+=item Added in BMO Bugzilla B<4.0>.
+
+=back
+
+=back
diff --git a/extensions/BMO/template/en/default/account/create.html.tmpl b/extensions/BMO/template/en/default/account/create.html.tmpl
new file mode 100644
index 000000000..8bd4a9812
--- /dev/null
+++ b/extensions/BMO/template/en/default/account/create.html.tmpl
@@ -0,0 +1,184 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Byron Jones <glob@mozilla.com>
+ #%]
+
+[%# INTERFACE
+ # none
+ #
+ # Param("maintainer") is used to display the maintainer's email.
+ # Param("emailsuffix") is used to pre-fill the email field.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% title = BLOCK %]
+ Create a new [% terms.Bugzilla %] account
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = title
+ style_urls = [ 'extensions/BMO/web/styles/create_account.css' ]
+%]
+
+<script type="text/javascript">
+function onSubmit() {
+ var email = document.getElementById('login').value;
+ if (email == '') {
+ alert('You must enter your email address.');
+ return false;
+ }
+ var isValid =
+ email.match(/@/)
+ && email.match(/@.+\./)
+ && !email.match(/\.$/)
+ && !email.match(/[\\()&<>,'"\[\]]/)
+ ;
+ if (!isValid) {
+ alert(
+ "The e-mail address doesn't pass our syntax checking for a legal " +
+ "email address.\n\nA legal address must contain exactly one '@', and " +
+ "at least one '.' after the @.\n\nIt must also not contain any of " +
+ "these special characters: \ ( ) & < > , ; : \" [ ], or any whitespace."
+ );
+ return false;
+ }
+ return true;
+}
+</script>
+
+<table border="0" id="create-account">
+<tr>
+
+<td width="50%" id="create-account-left" valign="top">
+
+ <h2 class="column-header">I need help using a Mozilla Product</h2>
+
+ <table border="0" id="product-list">
+ [% INCLUDE product
+ icon = "firefox"
+ name = "Firefox Support"
+ url = "http://support.mozilla.com/"
+ desc = "Support for the Firefox web browser."
+ %]
+ [% INCLUDE product
+ icon = "firefox"
+ name = "Firefox for Mobile Support"
+ url = "http://support.mozilla.com/mobile"
+ desc = "Support for the Firefox Mobile web browser."
+ %]
+ [% INCLUDE product
+ icon = "thunderbird"
+ name = "Thunderbird Support"
+ url = "http://www.mozillamessaging.com/support/"
+ desc = "Support for Thunderbird email client."
+ %]
+ [% INCLUDE product
+ icon = "other"
+ name = "Support for other products"
+ url = "http://www.mozilla.org/projects/"
+ desc = "Support for products not listed here."
+ %]
+ [% INCLUDE product
+ icon = "input"
+ name = "Feedback"
+ url = "http://input.mozilla.com/feedback"
+ desc = "Report issues with web site you use, or provide quick feedback for Firefox."
+ %]
+ [% INCLUDE product
+ icon = "idea"
+ name = "Ideas"
+ url = "http://input.mozilla.com/idea"
+ desc = "Offer us ideas on how to enhance Firefox."
+ %]
+ </table>
+
+</td>
+
+<td width="50%" id="create-account-right" valign="top">
+
+ <h2 class="column-header">I want to help</h2>
+
+ <div id="right-blurb">
+ <p>
+ Great! There are three things to know and do:
+ </p>
+ <ol>
+ <li>
+ Please consider reading our
+ <a href="https://developer.mozilla.org/en/Bug_writing_guidelines" target="_blank">[% terms.bug %] writing guidelines</a>.
+ </li>
+ <li>
+ [% terms.Bugzilla %] is a public place, so what you type and your email address will be visible
+ to all logged-in users. Some people use an
+ <a href="http://email.about.com/od/freeemailreviews/tp/free_email.htm" target="_blank">alternative email address</a>
+ for this reason.
+ </li>
+ <li>
+ Please give us an email address you want to use. Once we confirm that it works,
+ you'll be asked to set a password and then you can start filing [% terms.bugs %] and helping fix them.
+ </li>
+ </ol>
+ </div>
+
+ <h2 class="column-header">Create an account</h2>
+
+ <form method="post" action="createaccount.cgi" onsubmit="return onSubmit()">
+ <table id="create-account-form">
+ <tr>
+ <td class="label">Email Address:</td>
+ <td>
+ <input size="35" id="login" name="login" placeholder="you@example.com">[% Param('emailsuffix') FILTER html %]</td>
+ <td>
+ <input type="hidden" id="token" name="token" value="[% issue_hash_token(['create_account']) FILTER html %]">
+ <input type="submit" value="Create Account">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ [% Hook.process('additional_methods') %]
+
+</td>
+
+</tr>
+</table>
+
+<p id="bmo-admin">
+ If you think there's something wrong with [% terms.Bugzilla %], you can
+ <a href="mailto:bugzilla-admin@mozilla.org">send an email to the admins</a>, but
+ remember, they can't file [% terms.bugs %] for you, or solve tech support problems.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK product %]
+ <tr>
+ <td valign="top">
+ <a href="[% url FILTER none %]"><img
+ src="extensions/BMO/web/producticons/[% icon FILTER uri %].png"
+ border="0" width="64" height="64"></a>
+ </td>
+ <td valign="top">
+ <h2><a href="[% url FILTER none %]">[% name FILTER html %]</a></h2>
+ <div>[% desc FILTER html %]</div>
+ </td>
+ </tr>
+[% END %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-bootgecko-partner.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-bootgecko-partner.txt.tmpl
new file mode 100644
index 000000000..a718bdef6
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-bootgecko-partner.txt.tmpl
@@ -0,0 +1,23 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+What are the steps to reproduce?:
+[%+ cgi.param('steps_to_reproduce') %]
+
+What was the actual behavior?:
+[%+ cgi.param('actual_behavior') %]
+
+What was the expected behavior?:
+[%+ cgi.param('expected_behavior') %]
+
+What build were you using?: [% cgi.param('build') %]
+
+What are the requirements?: [% cgi.param('requirements') %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl
new file mode 100644
index 000000000..158c08f19
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl
@@ -0,0 +1,33 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Topic: [% cgi.param('topic') %]
+Presenter: [% cgi.param('presenter') %]
+Date: [% cgi.param('date') %]
+Time: [% cgi.param('time_hour') %]:[% cgi.param('time_minute') %][% cgi.param('ampm') +%] [%+ cgi.param('time_zone') %]
+Duration: [% IF cgi.param('duration') == 'Other' %][% cgi.param('duration_other') %][% ELSE %][% cgi.param('duration') %][% END %]
+Privacy: [% cgi.param('public') %]
+Large Screen Location: [% FOREACH location = cgi.param('large_screen_loc') %][% location FILTER html %], [% END %]
+Description:
+[%+ cgi.param('description') %]
+Special Requirements:
+[%+ cgi.param('special_requirements') %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-doc.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-doc.txt.tmpl
new file mode 100644
index 000000000..4c878a867
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-doc.txt.tmpl
@@ -0,0 +1,20 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi +%]
+:: Developer Documentation Request
+
+ Request Type: [% cgi.param("type") %]
+ Gecko Version: [% cgi.param("gecko") %]
+ Technical Contact: [% cgi.param("cc") %]
+
+:: Details
+
+[%+ cgi.param("details") %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl
new file mode 100644
index 000000000..1b0902d64
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl
@@ -0,0 +1,57 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% IF cgi.param('incident_type') == 'stolen' %]
+[% IF original_reporter -%]
+Reporter: [% original_reporter.identity FILTER none %]
+[%- END -%]
+
+ [% IF cgi.param('display_action') %]
+ [% IF cgi.param('display_action') == 'ldap' %]
+Action needed: Please immediately reset the LDAP password for this user.
+ [% ELSIF cgi.param('display_action') == 'ssh' %]
+Action needed: Please immediately disable the SSH key for this user.
+ [% END %]
+
+The user reported that their mobile or laptop device has been lost or stolen.
+This ticket was automatically generated from the employee incident reporting
+form. An additional ticket has been filed (see blocker bugs) for InfraSec to
+review the impact of this lost device.
+ [% END %]
+
+Type of device: [% cgi.param('device') %]
+Was the device encrypted?: [% cgi.param('encrypted') %]
+Any user data on the device?: [% cgi.param('userdata') %]
+ [% IF cgi.param('userdata') == 'Yes' %]
+Sensitive data on the device:
+[%+ cgi.param('sensitivedata') %]
+ [% END %]
+Browser configured to remember passwords?: [% cgi.param('rememberpasswords') %]
+ [% IF cgi.param('rememberpasswords') == 'Yes' %]
+Critical sites:
+[%+ cgi.param('criticalsites') %]
+ [% END %]
+[% END %]
+[% IF cgi.param('comment') %]
+Extra Notes:
+[%+ cgi.param('comment') %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-finance.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-finance.txt.tmpl
new file mode 100644
index 000000000..f0427b4c5
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-finance.txt.tmpl
@@ -0,0 +1,35 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Request Type: [% cgi.param('component') %]
+Summary: [% cgi.param('short_desc') %]
+Priority to your Team: [% cgi.param('team_priority') %]
+Timeframe for Signature: [% cgi.param('signature_time') %]
+
+Name of Other Party:
+[%+ cgi.param('other_party') %]
+
+Business Objective:
+[%+ cgi.param('business_obj') %]
+
+What is this purchase?:
+[%+ cgi.param('what_purchase') %]
+
+Why is this purchase needed?:
+[%+ cgi.param('why_purchase') %]
+
+What is the risk if this is not purchased?:
+[%+ cgi.param('risk_purchase') %]
+
+What is the alternative?:
+[%+ cgi.param('alternative_purchase') %]
+
+Total Cost: [% cgi.param('total_cost') %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-ipp.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-ipp.txt.tmpl
new file mode 100644
index 000000000..5c73587a9
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-ipp.txt.tmpl
@@ -0,0 +1,30 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi +%]
+:: Internet Public Policy Issue
+
+Region/Country: [% cgi.param("region") %]
+
+:: Description
+
+[%+ cgi.param("desc") %]
+
+:: Relevance
+
+[%+ cgi.param("relevance") %]
+
+Goal: [% cgi.param("goal") %]
+When: [% cgi.param("when") %]
+
+[% IF cgi.param("additional") %]
+:: Additional Information
+
+[%+ cgi.param("additional") %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl
new file mode 100644
index 000000000..eb00a88d9
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl
@@ -0,0 +1,39 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Priority for your Team:
+[%+ cgi.param('teampriority') %]
+
+Timeframe for Completion:
+[%+ cgi.param('timeframe') %]
+
+Goal:
+[%+ cgi.param('goal') %]
+
+Business Objective:
+[%+ cgi.param('busobj') %]
+
+Other Party:
+[%+ cgi.param('otherparty') %]
+
+Description:
+[%+ cgi.param("comment") %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-mdn.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mdn.txt.tmpl
new file mode 100644
index 000000000..60a443d2b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-mdn.txt.tmpl
@@ -0,0 +1,66 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi +%]
+
+[% IF cgi.param('request_type') == 'Bug' %]
+What did you do?
+================
+[%+ cgi.param('bug_actions') %]
+
+What happened?
+==============
+[%+ cgi.param('bug_actual_results') %]
+
+What should have happened?
+==========================
+[%+ cgi.param('bug_expected_results') %]
+
+[% ELSIF cgi.param('request_type') == 'Feature' %]
+What problems would this solve?
+===============================
+[%+ cgi.param('feature_problem_solving') %]
+
+Who would use this?
+===================
+[%+ cgi.param('feature_audience') %]
+
+What would users see?
+=====================
+[%+ cgi.param('feature_interface') %]
+
+What would users do? What would happen as a result?
+===================================================
+[%+ cgi.param('feature_process') %]
+
+[% ELSIF cgi.param('request_type') == 'Change' %]
+What feature should be changed? Please provide the URL of the feature if possible.
+==================================================================================
+[%+ cgi.param('change_feature') %]
+
+What problems would this solve?
+===============================
+[%+ cgi.param('change_problem_solving') %]
+
+Who would use this?
+===================
+[%+ cgi.param('change_audience') %]
+
+What would users see?
+=====================
+[%+ cgi.param('change_interface') %]
+
+What would users do? What would happen as a result?
+===================================================
+[%+ cgi.param('change_process') %]
+
+[% END %]
+Is there anything else we should know?
+======================================
+[%+ cgi.param("description") %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl
new file mode 100644
index 000000000..c62461d42
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl
@@ -0,0 +1,44 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ #%]
+[%# INTERFACE:
+ # This template has no interface.
+ #
+ # Form variables from a bug submission (i.e. the fields on a template from
+ # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to
+ # pull out various custom fields and format an initial Description entry
+ # from them.
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+List Name: [% cgi.param("listName") %]
+List Admin: [% cgi.param("listAdmin") %]
+
+Short Description:
+[%+ cgi.param("listShortDesc") %]
+
+[% IF cgi.param("listType") != "mozilla.com" %]
+Long Description:
+[%+ cgi.param("listLongDesc") %]
+[% END %]
+
+Justification / Special Instructions:
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-privacy-data.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-privacy-data.txt.tmpl
new file mode 100644
index 000000000..279d59b6b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-privacy-data.txt.tmpl
@@ -0,0 +1,30 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Where does this data come from:
+
+[%+ cgi.param('source') %]
+
+What people and things does this data describe, and what fields does it contain:
+
+[%+ cgi.param('data_desc') %]
+
+What parts of this data do you want to release:
+
+[%+ cgi.param('release') %]
+
+Why are we releasing this data, and what do we hope people will do with it:
+
+[%+ cgi.param('why') %]
+
+Is there a particular time by which you would like to release this data:
+
+[%+ cgi.param('when') %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl
new file mode 100644
index 000000000..9a38af7cc
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl
@@ -0,0 +1,28 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Recovery Key: [% cgi.param('recoverykey') %]
+Asset Tag Number: [% cgi.param('assettag') %]
+
+[% IF cgi.param('comment') %]
+[%+ cgi.param('comment') %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl
new file mode 100644
index 000000000..920d392da
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl
@@ -0,0 +1,50 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi +%]
+[% PROCESS global/variables.none.tmpl +%]
+:: Gear Requested
+
+ Purpose of Gear: [% cgi.param("purpose") %] [%+ cgi.param("purpose_other") %]
+ Date Required: [% cgi.param("date_required") || "-" %]
+
+[%+ cgi.param("items") %]
+
+:: Requester
+
+ Name: [% cgi.param('firstname') %] [% cgi.param('lastname') %]
+ Email: [% cgi.param('email') %]
+ Mozilla Space: [% cgi.param('mozspace') || "-" %]
+ Team/Department: [% cgi.param('teamcode') %]
+
+:: Recipient
+
+[% IF cgi.param("purpose") == "Mozillian Recognition" %]
+This [% terms.bug %] needs recipient shipping information: [% cgi.param("recognition_shipping") ? "Yes" : "No" %]
+This [% terms.bug %] needs recipient size information: [% cgi.param("recognition_sizing") ? "Yes" : "No" %]
+[% END %]
+
+ Name: [%+ cgi.param("shiptofirstname") +%] [%+ cgi.param("shiptolastname") +%]
+ Email: [%+ cgi.param("shiptoemail") +%]
+[% IF cgi.param("shiptoaddress1") %]
+ Address:
+ [%+ cgi.param("shiptoaddress1") +%]
+ [%+ cgi.param("shiptoaddress2") +%]
+ [%+ cgi.param("shiptocity") +%] [%+ cgi.param("shiptostate") +%] [%+ cgi.param("shiptopostcode") +%]
+ [%+ cgi.param("shiptocountry") %]
+ Phone: [% cgi.param("shiptophone") %]
+ Personal ID/RUT: [% cgi.param("shiptoidrut") || "-" %]
+[% END %]
+
+[% IF cgi.param("comment") %]
+:: Comments
+
+[%+ cgi.param("comment") %]
+[% END %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/create-bootgecko-partner.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-bootgecko-partner.html.tmpl
new file mode 100644
index 000000000..cdfd90174
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-bootgecko-partner.html.tmpl
@@ -0,0 +1,240 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_js = BLOCK %]
+ var compdesc = new Array();
+ compdesc[""] = 'Please select a component from the list above.';
+ [% FOREACH comp = product.components %]
+ compdesc['[% comp.name FILTER js %]'] = '[% comp.description FILTER js %]';
+ [% END %]
+ function showCompDesc(component) {
+ var value = component.value;
+ document.getElementById('comp_description').innerHTML = compdesc[value];
+ }
+ function onSubmit() {
+ var alert_text = '';
+ var status_whiteboard = '';
+
+ if (!isFilledOut('component'))
+ alert_text += "Please select a value for component.\n";
+ if (!isFilledOut('short_desc'))
+ alert_text += "Please enter a value for the summary.\n";
+ if (!isFilledOut('steps_to_reproduce'))
+ alert_text += "Please enter the steps to reproduce.\n";
+ if (!isFilledOut('actual_behavior'))
+ alert_text += "Please enter the actual behavior.\n";
+ if (!isFilledOut('expected_behavior'))
+ alert_text += "Please enter the expected behavior.\n";
+ if (!isFilledOut('build'))
+ alert_text += "Please enter a value for the build.\n";
+ if (!isFilledOut('requirements'))
+ alert_text += "Please enter a value for the requirements.\n";
+
+ var device_values = new Array();
+ var device_select = document.getElementById("b2g_device");
+ for (var i = 0, l = device_select.options.length; i < l; i++) {
+ if (device_select.options[i].selected)
+ device_values.push(device_select.options[i].value);
+ }
+
+ if (device_values.length == 0)
+ alert_text += "Please select one or more devices.\n";
+
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+
+ for (var i = 0, l = device_values.length; i < l; i++)
+ status_whiteboard += '[device:' + device_values[i] + '] ';
+
+ if (document.getElementById('third_party_app').checked)
+ status_whiteboard += '[apps watch list]';
+
+ document.getElementById('status_whiteboard').value = status_whiteboard;
+
+ return true;
+ }
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Boot2Gecko Partner $terms.Bug Submission"
+ style_urls = [ 'skins/standard/enter_bug.css' ]
+ javascript = inline_js
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/attachment.js', 'js/field.js', 'js/util.js' ]
+ onload = "showCompDesc(document.getElementById('component'));"
+%]
+
+<h2>Boot2Gecko Partner [% terms.Bug %] Submission</h2>
+
+<p>All fields are mandatory</p>
+
+<form method="post" action="post_bug.cgi" id="bug_form" class="enter_bug_form"
+ enctype="multipart/form-data" onsubmit="return onSubmit();">
+<input type="hidden" name="format" value="bootgecko-partner">
+<input type="hidden" name="product" value="Boot2Gecko">
+<input type="hidden" name="rep_platform" value="ARM">
+<input type="hidden" name="op_sys" value="Gonk (Firefox OS)">
+<input type="hidden" name="priority" value="--">
+<input type="hidden" name="version" value="unspecified">
+<input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+<input type="hidden" name="comment" id="comment" value="">
+<input type="hidden" name="keywords" id="keywords" value="unagi">
+<input type="hidden" name="status_whiteboard" id="status_whiteboard" value="">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table>
+
+<tr>
+ <th>
+ <label for="short_desc">Summary:</label>
+ </th>
+ <td>
+ <input name="short_desc" id="short_desc" size="60"
+ value="[% short_desc FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="component">Component:</label>
+ </th>
+ <td>
+ <select name="component" id="component" onchange="showCompDesc(this);">
+ <option value="">Select One</option>
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ id="v[% c.id FILTER html %]_component"
+ [% IF c.name == default.component_ %]
+ selected="selected"
+ [% END %]>
+ [% c.name FILTER html -%]
+ </option>
+ [%- END %]
+ </select
+ </td>
+</tr>
+
+<tr>
+ <td></td>
+ <td id="comp_description" align="left" style="color: green; padding-left: 1em"></td>
+</tr>
+
+<tr>
+ <th>
+ <label for="b2g_device">B2G Device:</label>
+ </th>
+ <td>
+ <select name="b2g_device" id="b2g_device"
+ size="5" multiple="multiple">
+ <option name="Otoro">Otoro</option>
+ <option name="Unagi">Unagi</option>
+ <option name="Inari">Inari</option>
+ <option name="Ikura">Ikura</option>
+ <option name="Hamachi">Hamachi</option>
+ <option name="Buri">Buri</option>
+ <option name="Toro">Toro</option>
+ <option name="Leo">Leo</option>
+ <option name="Twist">Twist</option>
+ <option name="Zero">Zero</option>
+ <option name="Tara">Tara</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="other_party">What are the steps to reproduce?:</label>
+ </th>
+ <td>
+ <textarea id="steps_to_reproduce" name="steps_to_reproduce" rows="5" cols="60">1.
+2.
+3.</textarea>
+ </td>
+<tr>
+
+<tr>
+ <th>
+ <label for="actual_behavior">What was the actual behavior?:</label>
+ </th>
+ <td>
+ <textarea id="actual_behavior" name="actual_behavior" rows="5" cols="60"></textarea>
+ </td>
+<tr>
+
+<tr>
+ <th>
+ <label for="expected_behavior">What was the expected behavior?:</label>
+ </th>
+ <td>
+ <textarea name="expected_behavior" id="expected_behavior" rows="5" cols="60"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="build">What build were you using?:</label>
+ </th>
+ <td>
+ <input type="text" name="build" id="build" value="" size="60">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="requirements">What are the requirements?:</label>
+ </th>
+ <td>
+ <input type="text" name="requirements" id="requirements" value="" size="60">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="requirements">Third party app content?:</label>
+ </th>
+ <td>
+ <input type="checkbox" name="third_party_app" id="third_party_app">
+ </td>
+</tr>
+
+<tr>
+ <th>Security:</th>
+ <td>
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+ <input type="checkbox" name="groups"
+ value="[% sec_group FILTER html %]" id="group_[% sec_group FILTER html %]"
+ [% FOREACH g = group %]
+ [% IF g.name == name %]
+ [% ' checked="checked"' IF g.checked %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+ >
+ <label for="group_[% sec_group FILTER html %]">
+ Many users could be harmed by this security problem:
+ it should be kept hidden from the public until it is resolved.
+ </label>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+</table>
+
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl
new file mode 100644
index 000000000..07c749f02
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl
@@ -0,0 +1,326 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Mozilla Corporation.
+ # Portions created by Mozilla are Copyright (C) 2008 Mozilla
+ # Corporation. All Rights Reserved.
+ #
+ # Contributor(s): Reed Loden <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Event Request"
+ style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }"
+ style_urls = [ 'skins/standard/enter_bug.css' ]
+ javascript_urls = [ 'js/attachment.js', 'js/field.js', 'js/util.js' ]
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+[% USE Bugzilla %]
+
+<script type="text/javascript">
+function trySubmit() {
+ var timeZone = document.getElementById('time_zone').value;
+ if (!timeZone) {
+ alert('You must select an appropriate time zone');
+ return false;
+ }
+ var topic = document.getElementById('topic').value;
+ var date = document.getElementById('date').value;
+ var time = document.getElementById('time_hour').value + ':' +
+ document.getElementById('time_minute').value + ' ' + timeZone;
+ var location = document.getElementById('location').value;
+ var shortdesc = 'Event - (' + date + ' ' + time + ') - ' + location + ' - ' + topic;
+ document.getElementById('short_desc').value = shortdesc;
+
+ var public = document.getElementById('public');
+ if (!public.value) {
+ alert('You must select whether the event is public or not');
+ return false;
+ }
+ if (public.value != 'The Public') {
+ var brownbagRequestForm = document.getElementById('brownbagRequestForm');
+ var groups = document.createElement('input');
+ groups.type = 'hidden';
+ groups.name = 'groups';
+ groups.value = 'mozilla-corporation-confidential';
+ brownbagRequestForm.appendChild(groups);
+ }
+
+ return true;
+}
+</script>
+
+<p>
+ <strong>Event Request:</strong> Please use this form to schedule an event
+ in any of the Mozilla Common Spaces.</b>
+</p>
+
+<p>Process:</p>
+
+<ol>
+ <li>Complete and submit request below.</li>
+ <li>Your request will be reviewed and assigned to the appropriate person in IT.</li>
+</ol>
+
+<form method="post" action="post_bug.cgi" id="brownbagRequestForm" class="enter_bug_form"
+ enctype="multipart/form-data" onSubmit="return trySubmit();">
+ <input type="hidden" name="format" value="brownbag">
+ <input type="hidden" name="product" value="Air Mozilla">
+ <input type="hidden" name="component" value="Events">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="comment" id="comment" value="">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table>
+<tr>
+ <th class="field_label">
+ <label for="presenter">Presenter:</label>
+ </th>
+ <td>
+ <input type="text" name="presenter" id="presenter" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="topic">Topic:</label>
+ </th>
+ <td>
+ <input type="text" name="topic" id="topic" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="date">Date:</label>
+ </th>
+ <td>
+ <input type="text" name="date" size="10" id="date"
+ align="right" value="" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date"
+ onclick="showCalendar('date')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_date"></div>
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="time_hour">Start Time (24 hr clock):</label>
+ </th>
+ <td>
+ <select name="time_hour" id="time_hour">
+ <option value="0">0</option>
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ <option value="12" selected>12</option>
+ <option value="13">13</option>
+ <option value="14">14</option>
+ <option value="15">15</option>
+ <option value="16">16</option>
+ <option value="17">17</option>
+ <option value="18">18</option>
+ <option value="19">19</option>
+ <option value="20">20</option>
+ <option value="21">21</option>
+ <option value="22">22</option>
+ <option value="23">23</option>
+ </select>:
+ <select name="time_minute" id="time_minute">
+ <option value="00" selected>00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+ </select>
+ <select name="time_zone" id="time_zone">
+ <option value="" selected>Select Time Zone</option>
+ <option value="UTC-14">UTC-14</option>
+ <option value="UTC-13">UTC-13</option>
+ <option value="UTC-12">UTC-12</option>
+ <option value="UTC-11">UTC-11</option>
+ <option value="UTC-10">UTC-10</option>
+ <option value="UTC-9">UTC-9</option>
+ <option value="UTC-8">UTC-8</option>
+ <option value="UTC-7">UTC-7</option>
+ <option value="UTC-6">UTC-6</option>
+ <option value="UTC-5">UTC-5</option>
+ <option value="UTC-4">UTC-4</option>
+ <option value="UTC-3">UTC-3</option>
+ <option value="UTC-2">UTC-2</option>
+ <option value="UTC-1">UTC-1</option>
+ <option value="UTC+0">UTC+0</option>
+ <option value="UTC+1">UTC+1</option>
+ <option value="UTC+2">UTC+2</option>
+ <option value="UTC+3">UTC+3</option>
+ <option value="UTC+4">UTC+4</option>
+ <option value="UTC+5">UTC+5</option>
+ <option value="UTC+6">UTC+6</option>
+ <option value="UTC+7">UTC+7</option>
+ <option value="UTC+8">UTC+8</option>
+ <option value="UTC+9">UTC+9</option>
+ <option value="UTC+10">UTC+10</option>
+ <option value="UTC+11">UTC+11</option>
+ <option value="UTC+12">UTC+12</option>
+ <option value="UTC+13">UTC+13</option>
+ <option value="UTC+14">UTC+14</option>
+ </select>
+ <br>
+ <table>
+ <tr>
+ <th>Summer:</th>
+ <td>MTV/SFO/PDX/YVR UTC-7</td>
+ <td>TOR/BOS UTC-4</td>
+ <td>LON UTC+1</td>
+ <td>PAR/BER UTC+2</td>
+ </tr>
+ <tr>
+ <th>Winter:</th>
+ <td>MTV/SFO/PDX/YVR UTC-8</td>
+ <td>TOR/BOS UTC-3</td>
+ <td>LON UTC</td>
+ <td>PAR/BER UTC+1</td>
+ </tr>
+ </table>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="duration_one_hour_radio">Duration:</label>
+ </th>
+ <td>
+ <input type="radio" name="duration" id="duration_one_hour_radio" value="1 Hour" checked="checked">
+ <label for="duration_one_hour_radio">1 Hour</label><br>
+ <input type="radio" name="duration" id="duration_one_day_radio" value="1 Day">
+ <label for="duration_one_day_radio">1 Day</label><br>
+ <input type="radio" name="duration" id="duration_other_radio" value="Other"
+ onclick="YAHOO.util.Dom.get('duration_other').focus();">
+ <label for="duration_other_radio">Other</label>
+ <input type="text" name="duration_other" id="duration_other" value="">
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="location">Originating Location:</label>
+ </th>
+ <td>
+ <input type="text" name="location" id="location"
+ value="[% default.location || 'Ten Forward' FILTER html %]" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="large_screen_loc_mtv_radio">Show on large screens in<br>these Mozilla Spaces Commons:</label>
+ </th>
+ <td>
+ <input type="checkbox" name="large_screen_loc" id="large_screen_loc_mtv_checkbox" value="MTV" checked="checked">
+ <label for="large_screen_loc_mtv_checkbox">MTV</label><br>
+ <input type="checkbox" name="large_screen_loc" id="large_screen_loc_sfo_checkbox" value="SFO">
+ <label for="large_screen_loc_sfo_checkbox">SFO</label><br>
+ <input type="checkbox" name="large_screen_loc" id="large_screen_loc_tor_checkbox" value="TOR">
+ <label for="large_screen_loc_tor_checkbox">TOR</label><br>
+ <input type="checkbox" name="large_screen_loc" id="large_screen_loc_lon_checkbox" value="LON">
+ <label for="large_screen_loc_lon_checkbox">LON</label><br>
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">This event may be seen by:</th>
+ <td>
+ If anything other than <strong>The Public</strong> is chosen, this request will only be
+ visible internally as well as the reporter and anyone designated in the CC field.<br>
+ <select name="public" id="public">
+ <option value="">Select One</option>
+ <option value="The Public">The Public</option>
+ <option value="Vouched Mozillians and MoCo/MoFo Staff">Vouched Mozillians and MoCo/MoFo Staff</option>
+ <option value="MoCo/MoFo Staff Only">MoCo/MoFo Staff Only</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="cc">CC&nbsp;(optional):</label>
+ </th>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="description">Description</label>:
+ </th>
+ <td>
+ Please describe the event the way you would in a program guide listing<br>
+ <textarea id="description" name="description" rows="10" cols="80"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th class="field_label">
+ <label for="special_requirements">Special Requirements:</label>
+ </th>
+ <td>
+ <textarea id="special_requirements" name="special_requirements" rows="10" cols="80"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td></td>
+ <td>
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+</table>
+
+</form>
+
+<p>
+ Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+</p>
+
+<script type="text/javascript">
+ createCalendar('date');
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-doc.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-doc.html.tmpl
new file mode 100644
index 000000000..37d0fa0f6
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-doc.html.tmpl
@@ -0,0 +1,220 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_style = BLOCK %]
+#doc_form th {
+ text-align: right;
+}
+
+#short_desc, #details {
+ width: 100%;
+}
+[% END %]
+
+[% inline_javascript = BLOCK %]
+function validateAndSubmit() {
+ var alert_text = '';
+ if (!isFilledOut('type')) alert_text += 'Please select the "Request Type".\n';
+ if (!isFilledOut('short_desc')) alert_text += 'Please enter a "Summary".\n';
+ if (!isFilledOut('gecko')) alert_text += 'Please select the "Gecko Version".\n';
+ if (!isFilledOut('details')) alert_text += 'Please enter some "Details".\n';
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+ return true;
+}
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Developer Documentation Request"
+ style = inline_style
+ javascript = inline_javascript
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js', 'js/util.js', 'js/bug.js' ]
+ yui = [ 'autocomplete', 'datatable', 'button' ]
+%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+<h1>Developer Documentation Request</h1>
+
+<p>
+ Use this form to request <b>new documentation</b> or <b>corrections</b> to existing documentation.<br>
+ [ <span class="required_star">*</span> <span class="required_explanation">Required Fields</span> ]
+</p>
+
+<form method="post" action="post_bug.cgi" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+ <input type="hidden" name="format" value="doc">
+ <input type="hidden" name="product" value="Developer Documentation">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="doc_form">
+
+<tr>
+ <th class="required">Request Type</th>
+ <td>
+ <select name="type" id="type">
+ <option value="">Please select..</option>
+ <option value="New Documentation">New Documentation</option>
+ <option value="Correction" [% "selected" IF cgi.param('bug_file_loc') %]>Correction</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Topic</th>
+ <td>
+ <select name="component" id="component">
+ [% FOREACH component = product.components %]
+ <option value="[% component.name FILTER html %]"
+ [% " selected" IF component.name == "General" %]>
+ [% component.name FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Summary</th>
+ <td>
+ Please provide a brief summary of what documentation you're requesting, or
+ what problem you're reporting in existing documentation:<br>
+ <input type="text" name="short_desc" id="short_desc" size="60">
+ </td>
+</tr>
+
+[% IF feature_enabled('jsonrpc') AND !cloned_bug_id %]
+ <tr id="possible_duplicates_container" class="bz_default_hidden">
+ <th>Possible<br>Duplicates:</th>
+ <td colspan="3">
+ <div id="possible_duplicates"></div>
+ <script type="text/javascript">
+ var dt_columns = [
+ { key: "id", label: "[% field_descs.bug_id FILTER js %]",
+ formatter: YAHOO.bugzilla.dupTable.formatBugLink },
+ { key: "summary",
+ label: "[% field_descs.short_desc FILTER js %]",
+ formatter: "text" },
+ { key: "status",
+ label: "[% field_descs.bug_status FILTER js %]",
+ formatter: YAHOO.bugzilla.dupTable.formatStatus },
+ { key: "update_token", label: '',
+ formatter: YAHOO.bugzilla.dupTable.formatCcButton }
+ ];
+ YAHOO.bugzilla.dupTable.addCcMessage = "Add Me to the CC List";
+ YAHOO.bugzilla.dupTable.init({
+ container: 'possible_duplicates',
+ columns: dt_columns,
+ product_name: '[% product.name FILTER js %]',
+ summary_field: 'short_desc',
+ options: {
+ MSG_LOADING: 'Searching for possible duplicates...',
+ MSG_EMPTY: 'No possible duplicates found.',
+ SUMMARY: 'Possible Duplicates'
+ }
+ });
+ </script>
+ </td>
+ </tr>
+[% END %]
+
+<tr>
+ <th>Page to Update</th>
+ <td>
+ <input type="text" name="bug_file_loc" id="short_desc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <th>Technical Contact</th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => ""
+ size => 60
+ classes => ["bz_userfield"]
+ multiple => 5
+ %]
+ <br>
+ <a href="https://developer.mozilla.org/en-US/docs/Project:Subject-matter_experts"
+ target="_blank" id="common_topic_experts">
+ List of common topic experts</a>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Gecko Version</th>
+ <td>
+ <select name="gecko" id="gecko">
+ [% FOREACH version = versions %]
+ <option value="[% version.name FILTER html %]"
+ [% " selected" IF version.name == "unspecified" %]>
+ [% version.name FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Details</th>
+ <td>
+ <textarea id="details" name="details" cols="50" rows="10"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>Development [% terms.Bug %]</th>
+ <td>
+ <input type="text" id="blocked" name="blocked" size="10">
+ <i>Corresponding development [% terms.bug %].</i>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Urgency</th>
+ <td>
+ <select name="priority" id="priority">
+ <option value="P1">Immediately</option>
+ <option value="P2">Before Release</option>
+ <option value="P3">Before Aurora</option>
+ <option value="P4">Before Beta</option>
+ <option value="P5" selected>No Rush</option>
+ </select>
+ <br>
+ Due to the volume of requests, the documentation team can't commit to
+ meeting specific deadlines for given documentation requests, but we will do
+ our best.
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td><input type="submit" id="commit" value="Submit Request"></td>
+</tr>
+
+</table>
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl
new file mode 100644
index 000000000..2bbacdb12
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl
@@ -0,0 +1,288 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation/Foundation Employee Incident"
+%]
+
+[% USE Bugzilla %]
+
+<script type="text/javascript">
+ var type_desc = new Array();
+ type_desc['safety'] = "If this is an emergency please immediately call your local police or emergency number.";
+ type_desc['stolen'] = "Please report a lost Mozilla laptop or any mobile device that was used to access<br> " +
+ "Mozilla email or contained passwords for Mozilla servers, devices, applications, etc.";
+
+ function validateAndSubmit() {
+ var alert_text = '';
+ var typeSelect = YAHOO.util.Dom.get('incident_type');
+ var typeValue = typeSelect.options[typeSelect.selectedIndex].value;
+
+ if (typeValue != 'stolen' && !isFilledOut('short_desc')) {
+ alert_text += "Please enter a summary.\n";
+ }
+
+ var select = YAHOO.util.Dom.get('incident_type');
+ var selectValue = select.options[select.selectedIndex].value;
+ if (selectValue == 'stolen') {
+ if (!isFilledOut('device')) {
+ alert_text += "Please provide the type of device.\n";
+ }
+ if (!isFilledOut('encrypted')) {
+ alert_text += "Please answer whether the device was encrypted.\n";
+ }
+ if (!isFilledOut('userdata')) {
+ alert_text += "Please answer whether the device had user data.\n";
+ }
+ if (!isFilledOut('rememberpasswords')) {
+ alert_text += "Please answer whether the browser was configured to remember passwords.\n";
+ }
+ }
+
+ if (alert_text) {
+ alert(alert_text);
+ return false;
+ }
+
+ // Hard code summary if stolen type was chosen
+ if (typeValue == 'stolen') {
+ document.getElementById('short_desc').value = '[Lost Device] Change LDAP Password for [% user.name FILTER js %]';
+ }
+
+ return true;
+ }
+
+ function setType (select) {
+ var selectValue = select.options[select.selectedIndex].value;
+
+ // Set the current description displayed.
+ document.getElementById('type_desc').innerHTML = type_desc[selectValue];
+
+ // Display/hide some additional fields based on type selected
+ if (selectValue == 'stolen') {
+ YAHOO.util.Dom.removeClass('stolen', 'bz_default_hidden');
+ YAHOO.util.Dom.addClass('safety', 'bz_default_hidden');
+ }
+ else {
+ YAHOO.util.Dom.removeClass('safety', 'bz_default_hidden');
+ YAHOO.util.Dom.addClass('stolen', 'bz_default_hidden');
+ }
+
+ // Alter the product/component/group based on type selected
+ if (selectValue == 'stolen') {
+ document.getElementById('product').value = 'mozilla.org';
+ document.getElementById('component').value = 'Server Operations: Desktop Issues';
+ document.getElementById('groups').value = 'infra';
+ document.getElementById('cc').value = 'mcoates@mozilla.com, jstevensen@mozilla.com, afowler@mozilla.com';
+ document.getElementById('bug_severity').value = 'critical';
+ document.getElementById('display_action').value = 'ldap';
+ }
+ else {
+ document.getElementById('product').value = 'Mozilla Corporation';
+ document.getElementById('component').value = 'Facilities Management';
+ document.getElementById('groups').value = 'hr';
+ document.getElementById('cc').value = 'dcohen@mozilla.com, mcoates@mozilla.com, jill@mozilla.com';
+ document.getElementById('bug_severity').value = 'normal';
+ document.getElementById('display_action').value = '';
+ }
+ }
+
+ function toggleEnabled (source, value, target) {
+ var sourceElement = YAHOO.util.Dom.get(source);
+ var targetElement = YAHOO.util.Dom.get(target);
+ if (sourceElement[sourceElement.selectedIndex].value == value) {
+ targetElement.disabled = false;
+ targetElement.focus();
+ }
+ else {
+ targetElement.disabled = true;
+ }
+ }
+
+ function isFilledOut(elem_id) {
+ var str = document.getElementById(elem_id).value;
+ return str.length > 0 && str != "noneselected";
+ }
+
+ YAHOO.util.Event.onDOMReady(function () {
+ setType(document.getElementById('incident_type'));
+ toggleEnabled('userdata', 'Yes', 'sensitivedata');
+ toggleEnabled('rememberpasswords', 'Yes', 'criticalsites');
+ });
+</script>
+
+<p><strong>Please use this form for employee incidents only!</strong></p>
+<p>If you have a [% terms.bug %] to file, go <a href="enter_bug.cgi">here</a>.</p>
+<p><span style="color: red;">*</span> Required Fields</p>
+<form method="post" action="post_bug.cgi" id="incidentForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+ <input type="hidden" id="product" name="product" value="">
+ <input type="hidden" id="component" name="component" value="">
+ <input type="hidden" id="rep_platform" name="rep_platform" value="All">
+ <input type="hidden" id="op_sys" name="op_sys" value="All">
+ <input type="hidden" id="priority" name="priority" value="--">
+ <input type="hidden" id="version" name="version" value="other">
+ <input type="hidden" id="cc" name="cc" value="">
+ <input type="hidden" id="groups" name="groups" value="">
+ <input type="hidden" id="format" name="format" value="employee-incident">
+ <input type="hidden" id="bug_severity" name="bug_severity" value="">
+ <input type="hidden" id="display_action" name="display_action" value="">
+ <input type="hidden" id="token" name="token" value="[% token FILTER html %]">
+
+ <table>
+ <tr>
+ <td align="right" valign="top"><strong>Incident Type:</strong></td>
+ <td>
+ <select id="incident_type" name="incident_type" onchange="setType(this);">
+ <option value="safety" selected>Report a Safety Concern</option>
+ <option value="stolen">My laptop or phone was lost/stolen</option>
+ </select>
+ <div id="type_desc" style="color:red;"></div>
+ </td>
+ </tr>
+ <tbody id="safety" class="bz_default_hidden">
+ <tr class="safety">
+ <td align="right">
+ <strong><span style="color: red;">*</span> Summary:</strong>
+ </td>
+ <td>
+ <input name="short_desc" id="short_desc" size="60"
+ value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+ </tbody>
+ <tbody id="stolen" class="bz_default_hidden">
+ <tr>
+ <td align="right" valign="top"><strong>Stolen Details:</strong></td>
+ <td>
+ <table>
+ <tr>
+ <td>
+ <label for="device">
+ <strong><span style="color: red;">*</span></strong>
+ Type of device lost:
+ </label>
+ </td>
+ <td>
+ <select name="device" id="device">
+ <option value="">---</option>
+ <option value="Mobile Phone">Mobile Phone</option>
+ <option value="Tablet">Tablet</option>
+ <option value="Laptop">Laptop</option>
+ <option value="WorkStation">WorkStation</option>
+ <option value="Portable Storage Device">Portable Storage Device</option>
+ <option value="Other">Other (describe in 'Extra Notes')</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label for="encrypted">
+ <strong><span style="color: red;">*</span></strong>
+ To your knowledge, was your device encrypted?
+ </label>
+ </td>
+ <td>
+ <select name="encrypted" id="encrypted">
+ <option value="">---</option>
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label for="userdata">
+ <strong><span style="color: red;">*</span></strong>
+ Did you have any user data on your device?
+ </label>
+ </td>
+ <td>
+ <select name="userdata" id="userdata"
+ onchange="toggleEnabled('userdata', 'Yes', 'sensitivedata');">
+ <option value="">---</option>
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>If yes, what sensitive data was stored on your device?</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <textarea name="sensitivedata" id="sensitivedata" rows="10" cols="80"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <label for="rememberpasswords">
+ <strong><span style="color: red;">*</span></strong>
+ Was your browser configured to remember passwords
+ (<a href="http://support.mozilla.com/en-US/kb/make-firefox-remember-usernames-and-passwords">more info</a>)?
+ </label>
+ <select name="rememberpasswords" id="rememberpasswords"
+ onchange="toggleEnabled('rememberpasswords', 'Yes', 'criticalsites');">
+ <option value="">---</option>
+ <option value="No">No</option>
+ <option value="Yes">Yes</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>If yes, which critical sites were included?</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <textarea name="criticalsites" id="criticalsites" rows="10" cols="80"></textarea>
+ </td>
+ </tr>
+ </tbody>
+ <tr>
+ <td align="right" valign="top"><strong>Extra Notes:</strong></td>
+ <td>
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+ </tr>
+ </table>
+</form>
+
+<p>
+ Thanks for contacting us. You will be notified by email of any progress made in resolving your request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-finance.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-finance.html.tmpl
new file mode 100644
index 000000000..fa8dc5f5b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-finance.html.tmpl
@@ -0,0 +1,257 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_style = BLOCK %]
+ #bug_form input[type=text], #bug_form input[type=file], #cc_autocomplete, #bug_form textarea {
+ width: 100%;
+ }
+[% END %]
+
+[% inline_js = BLOCK %]
+ var compdesc = new Array();
+ [% FOREACH comp = product.components %]
+ compdesc['[% comp.name FILTER js %]'] = '[% comp.description FILTER js %]';
+ [% END %]
+ function showCompDesc(component) {
+ var value = component.value;
+ document.getElementById('comp_description').innerHTML = compdesc[value];
+ }
+
+ function onSubmit() {
+ var alert_text = '';
+ if (!isFilledOut('component'))
+ alert_text += "Please select a value for request type.\n";
+ if (!isFilledOut('short_desc'))
+ alert_text += "Please enter a value for the summary.\n";
+ if (!isFilledOut('team_priority'))
+ alert_text += "Please select a value for team priority.\n";
+ if (!isFilledOut('signature_time'))
+ alert_text += "Please enter a value for signture timeframe.\n";
+ if (!isFilledOut('other_party'))
+ alert_text += "Please enter a value for the name of other party.\n";
+ if (!isFilledOut('business_obj'))
+ alert_text += "Please enter a value for business objective.\n";
+ if (!isFilledOut('what_purchase'))
+ alert_text += "Please enter a value for what you are purchasing.\n";
+ if (!isFilledOut('why_purchase'))
+ alert_text += "Please enter a value for why the purchase is needed.\n";
+ if (!isFilledOut('risk_purchase'))
+ alert_text += "Please enter a value for the risk if not purchased.\n";
+ if (!isFilledOut('alternative_purchase'))
+ alert_text += "Please enter a value for the purchase alternative.\n";
+ if (!isFilledOut('total_cost'))
+ alert_text += "Please enter a value for total cost.\n";
+ if (!isFilledOut('attachment'))
+ alert_text += "Please enter an attachment.\n";
+
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+
+ return true;
+ }
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Finance"
+ style = inline_style
+ style_urls = [ 'skins/standard/enter_bug.css' ]
+ javascript = inline_js
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/attachment.js', 'js/field.js', 'js/util.js' ]
+ onload = "showCompDesc(document.getElementById('component'));"
+%]
+
+<h2>Finance</h2>
+
+<p>All fields are mandatory</p>
+
+<form method="post" action="post_bug.cgi" id="bug_form" class="enter_bug_form"
+ enctype="multipart/form-data" onsubmit="return onSubmit();">
+<input type="hidden" name="format" value="finance">
+<input type="hidden" name="product" value="Finance">
+<input type="hidden" name="rep_platform" value="All">
+<input type="hidden" name="op_sys" value="Other">
+<input type="hidden" name="priority" value="--">
+<input type="hidden" name="version" value="unspecified">
+<input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+<input type="hidden" name="comment" id="comment" value="">
+<input type="hidden" name="groups" id="groups" value="finance">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table>
+
+<tr>
+ <th>
+ <label for="component">Request Type:</label>
+ </th>
+ <td>
+ <select name="component" id="component" onchange="showCompDesc(this);">
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ id="v[% c.id FILTER html %]_component"
+ [% IF c.name == default.component_ %]
+ selected="selected"
+ [% END %]>
+ [% c.name FILTER html -%]
+ </option>
+ [%- END %]
+ </select
+ </td>
+</tr>
+
+<tr>
+ <td></td>
+ <td id="comp_description" align="left" style="color: green; padding-left: 1em"></td>
+</tr>
+
+<tr>
+ <th>
+ <label for="short_desc">Description:</label>
+ </th>
+ <td>
+ <i>Short description of what is being asked to sign</i><br>
+ <input name="short_desc" id="short_desc" size="60"
+ value="[% short_desc FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="team_priority">Priority to your Team:</label>
+ </th>
+ <td>
+ <select id="team_priority" name="team_priority">
+ <option value="Low">Low</option>
+ <option value="Medium">Medium</option>
+ <option value="High">High</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="signature_time">Timeframe for Signature:</label>
+ </th>
+ <td>
+ <select id="signature_time" name="signature_time">
+ <option value="24 hours">Within 24 hours</option>
+ <option value="2 days">2 days</option>
+ <option value="A week">A week</option>
+ <option value="2 - 4 weeks" selected>2 -4 weeks</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="other_party">Name of Other Party:</label>
+ </th>
+ <td>
+ <i>Include full legal entity name and any other relevant contact information</i><br>
+ <textarea id="other_party" name="other_party"
+ rows="5" cols="40"></textarea>
+ </td>
+<tr>
+
+<tr>
+ <th>
+ <label for="business_obj">Business Objective:</label>
+ </th>
+ <td>
+ <i>
+ Which Initiative or Overall goal this purchase is for. i.e. B2G, Data Center, Network, etc.</i><br>
+ <textarea id="business_obj" name="business_obj" rows="5" cols="40"></textarea>
+ </td>
+<tr>
+
+<tr>
+ <th>
+ <label for="what_purchase">If this is a purchase order,<br>what are we purchasing?</label>
+ </th>
+ <td>
+ <i>
+ Describe your request, what items are we purchasing, including number of
+ units if available.<br>Also provide context and background. Enter No if not
+ a purchase order.</i><br>
+ <textarea name="what_purchase" id="what_purchase" rows="5" cols="40"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="why_purchase">Why is this purchase needed?</label>
+ </th>
+ <td>
+ <i>
+ Why do we need this? What is the work around if this is not approved?</i><br>
+ <textarea name="why_purchase" id="why_purchase" rows="5" cols="40"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="risk_purchase">What is the risk if<br>this is not purchased?</label>
+ </th>
+ <td>
+ <i>
+ What will happen if this is not purchased?</i><br>
+ <textarea name="risk_purchase" id="risk_purchase" rows="5" cols="40"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="alternative_purchase">What is the alternative?</label>
+ </th>
+ <td>
+ <i>
+ How did the team come to this recommendation? Did we get other bids, if so, how many?</i><br>
+ <textarea name="alternative_purchase" id="alternative_purchase" rows="5" cols="40"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="total_cost">Total Cost</label>
+ </th>
+ <td>
+ <input type="text" name="total_cost" id="total_cost" value="" size="60">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="attachment">Attachment:</label>
+ </th>
+ <td>
+ <i>Upload document that needs to be signed. If this is a Purchase Request form,<br>
+ also upload any supporting document such as draft SOW, quote, order form, etc.</i>
+ <div>
+ <input type="file" id="attachment" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect">
+ <input type="hidden" name="description" value="Finance Document">
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+</table>
+
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-ipp.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-ipp.html.tmpl
new file mode 100644
index 000000000..0bf75f4a9
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-ipp.html.tmpl
@@ -0,0 +1,163 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_style = BLOCK %]
+#ipp_form th {
+ text-align: right;
+}
+
+#ipp_form input[type="text"], #ipp_form textarea {
+ width: 100%;
+}
+
+#ipp_form textarea {
+ font-family: inherit;
+ font-size: inherit;
+}
+[% END %]
+
+[% inline_javascript = BLOCK %]
+function validateAndSubmit() {
+ var alert_text = '';
+ if (!isFilledOut('component')) alert_text += 'Please select the "Area".\n';
+ if (!isFilledOut('short_desc')) alert_text += 'Please enter a "Summary".\n';
+ if (!isFilledOut('region')) alert_text += 'Please enter the "Region/Country".\n';
+ if (!isFilledOut('desc')) alert_text += 'Please provide a "Description".\n';
+ if (!isFilledOut('relevance')) alert_text += 'Please provide some "Relevance".\n';
+ if (!isFilledOut('goal')) alert_text += 'Please enter the "Goal".\n';
+ if (!isFilledOut('when')) alert_text += 'Please enter data for the "When" field.\n';
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+ return true;
+}
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Internet Public Policy Issue"
+ style = inline_style
+ javascript = inline_javascript
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js', 'js/util.js', 'js/bug.js' ]
+%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+<h1>Internet Public Policy Issue</h1>
+
+<form method="post" action="post_bug.cgi" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+ <input type="hidden" name="format" value="ipp">
+ <input type="hidden" name="product" value="Internet Public Policy">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="ipp_form">
+
+<tr>
+ <th class="required">Area</th>
+ <td>
+ <select name="component" id="component">
+ <option value="">Please select..</option>
+ [% FOREACH component = product.components %]
+ <option value="[% component.name FILTER html %]">
+ [% component.name FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Summary</th>
+ <td>
+ <input type="text" name="short_desc" id="short_desc" size="60"
+ placeholder="(Describe issue in one sentence)">
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Region/Country</th>
+ <td>
+ <input type="text" name="region" id="region" size="60">
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Description</th>
+ <td>
+ <textarea id="desc" name="desc" cols="50" rows="5"
+ placeholder="(Explain the legislative or policy activity which is happening)"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Relevance</th>
+ <td>
+ <textarea id="relevance" name="relevance" cols="50" rows="5"
+ placeholder="(Why should Mozilla care? What’s the impact on the open internet?)"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Goal</th>
+ <td>
+ <input type="text" name="goal" id="goal" size="60"
+ placeholder="(What would success look like for Mozilla?)">
+ </td>
+</tr>
+
+<tr>
+ <th class="required">When</th>
+ <td>
+ <input type="text" name="when" id="when" size="60"
+ placeholder="(Describe the timeline or due date)">
+ </td>
+</tr>
+
+<tr>
+ <th class="required">Urgency</th>
+ <td>
+ <select name="priority" id="priority">
+ <option value="P1">Urgent</option>
+ <option value="P3">Needs Attention Soon</option>
+ <option value="P5" selected>When You Get To It</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th>Additional Information</th>
+ <td>
+ <textarea id="additional" name="additional" cols="50" rows="5"
+ placeholder="(Please supply links to relevant articles/websites/organizations)"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td><input type="submit" id="commit" value="Submit Issue"></td>
+</tr>
+
+</table>
+</form>
+
+[ <span class="required_star">*</span> <span class="required_explanation">Required Field</span> ]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl
new file mode 100644
index 000000000..0db96e893
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl
@@ -0,0 +1,230 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_javascript = BLOCK %]
+ function setsevdesc(theSelect) {
+ var theValue = theSelect.options[theSelect.selectedIndex].value;
+ if (theValue == 'blocker') {
+ document.getElementById('blockerdesc').style.display = 'block';
+ document.getElementById('critdesc').style.display = 'none';
+ } else if (theValue == 'critical') {
+ document.getElementById('blockerdesc').style.display = 'none';
+ document.getElementById('critdesc').style.display = 'block';
+ } else {
+ document.getElementById('blockerdesc').style.display = 'none';
+ document.getElementById('critdesc').style.display = 'none';
+ }
+ }
+
+ var compdesc = new Array();
+ [% FOREACH comp IN product.components %]
+ compdesc['[% comp.name FILTER js %]'] = '[% comp.description FILTER js %]';
+ [% END %]
+ compdesc['invalid'] = '';
+
+ var serviceNowText = 'Use <a href="https://mozilla.service-now.com/">Service Now</a> to:<br>' +
+ 'Request an LDAP/E-mail/etc. account<br>' +
+ 'Desktop/Laptop/Printer/Phone/Tablet/License problem/order/request';
+
+ function setcompdesc(theRadio) {
+ if (theRadio.id == 'componentmvd') {
+ [%# helpdesk issue/request %]
+ document.getElementById('main_form').style.display = 'none';
+ document.getElementById('service_now_form').style.display = '';
+ document.getElementById('compdescription').innerHTML = serviceNowText;
+ } else {
+ document.getElementById('main_form').style.display = '';
+ document.getElementById('service_now_form').style.display = 'none';
+ var theValue = theRadio.value;
+ var compDescText = compdesc[theValue];
+ if (theRadio.id == 'componentso') {
+ compDescText = compDescText + '<br><br>' + serviceNowText;
+ }
+ document.getElementById('compdescription').innerHTML = compDescText;
+ }
+ }
+
+ function on_submit() {
+ if (document.getElementById('componentmvd').checked) {
+ [%# redirect desktop issues to service-now #%]
+ document.location.href = 'https://mozilla.service-now.com/';
+ return false;
+ }
+ return true;
+ }
+
+ YAHOO.util.Event.onDOMReady(function() {
+ var comps = document.getElementsByName('component');
+ for (var i = 0, l = comps.length; i < l; i++) {
+ if (comps[i].checked) {
+ setcompdesc(comps[i]);
+ break;
+ }
+ }
+ });
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation/Foundation IT Requests"
+ javascript = inline_javascript
+ javascript_urls = [ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+[% USE Bugzilla %]
+
+<p><strong>Please use this form for IT requests only!</strong></p>
+<p>If you have a [% terms.bug %] to file, go <a href="enter_bug.cgi">here</a>.</p>
+
+<form method="post" action="post_bug.cgi" id="itRequestForm" enctype="multipart/form-data"
+ onsubmit="return on_submit()">
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ <table>
+ <tr>
+
+ <td align="right">
+ <strong>Urgency:</strong>
+ </td>
+
+ <td>
+ <select id="bug_severity" name="bug_severity" onchange="setsevdesc(this)">
+ <option value="blocker">All work for IT stops until this is done</option>
+ <option value="critical">IT should work on it soon as possible (urgent)</option>
+ <option value="major">IT should get to it within 24 hours</option>
+ <option value="normal">IT should get to it within the next week</option>
+ <option value="minor" selected="selected">No rush, but hopefully IT can get to it soon</option>
+ <option value="trivial">Whenever IT can get around to it</option>
+ <option value="enhancement">This is just an idea, filing it so we don't forget</option>
+ </select>
+ </td>
+ <td>
+ <div id="blockerdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 30 minutes.</div>
+ <div id="critdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 8 hours.</div>
+ </td>
+
+ </tr>
+ <tr>
+ <td align="right"><strong>Request Type:</strong></td>
+ <td style="white-space: nowrap;">
+ <input type="radio" name="component" id="componentmvd" onclick="setcompdesc(this)" value="Server Operations: Desktop Issues">
+ <label for="componentmvd">Desktop issue/request</label><br>
+ <input type="radio" name="component" id="componenttbm" onclick="setcompdesc(this)" value="Server Operations: RelEng">
+ <label for="componenttbm">Report a problem with a tinderbox machine</label><br>
+ <input type="radio" name="component" id="componentwcp" onclick="setcompdesc(this)" value="Server Operations: Web Operations">
+ <label for="componentwcp">Report a problem with a Mozilla website, or to request a change or push</label><br>
+ <input type="radio" name="component" id="componentacl" onclick="setcompdesc(this)" value="Server Operations: ACL Request">
+ <label for="componentacl">Request a firewall change</label><br>
+ <input type="radio" name="component" id="componentso" onclick="setcompdesc(this)" value="Server Operations">
+ <label for="componentso">Any other issue</label><br>
+ Mailing list requests should be filed <a href="[% ulrbase FILTER none %]enter_bug.cgi?product=mozilla.org&amp;format=mozlist">here</a> instead.
+ </td>
+ <td id="compdescription" align="left" style="color: green; padding-left: 1em">
+ </td>
+ </tr>
+
+ <tbody id="main_form">
+
+ <tr>
+ <td align="right"><strong>Summary:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Description:</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td colspan="4">&nbsp;</td></tr>
+
+ <tr>
+ <td colspan="4">
+ <strong>Attachment&nbsp;(optional):</strong>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">File:</td>
+ <td colspan="3">
+ <em>Enter the path to the file on your computer.</em><br>
+ <input type="file" id="data" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect" />
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">Description:</td>
+ <td colspan="3">
+ <em>Describe the attachment briefly.</em><br>
+ <input type="text" id="description" name="description" size="60" maxlength="200">
+ </td>
+ </tr>
+
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <br>
+ <!-- infra -->
+ <input type="checkbox" name="groups" id="groups" value="infra" checked="checked">
+ <label for="groups"><strong>This is an internal issue which should not be publicly visible.</strong></label><br>
+ (please uncheck this box if it isn't)<br>
+ <br>
+ <input type="submit" id="commit" value="Submit Request"><br>
+ <br>
+ Thanks for contacting us. You will be notified by email of any progress made in resolving your request.
+ </td>
+ </tr>
+
+ </tbody>
+
+ <tbody id="service_now_form" style="display:none">
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <br>
+ <input type="submit" value="Go to Service Now">
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</form>
+
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl
new file mode 100644
index 000000000..fdb92c11b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl
@@ -0,0 +1,226 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Mozilla Corporation.
+ # Portions created by Mozilla are Copyright (C) 2008 Mozilla
+ # Corporation. All Rights Reserved.
+ #
+ # Contributor(s): Mark Smith <mark@mozilla.com>
+ # Reed Loden <reed@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation Legal Requests"
+ style_urls = [ 'skins/standard/attachment.css' ]
+ javascript_urls = [ 'js/attachment.js', 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+[% IF user.in_group("mozilla-corporation-confidential")
+ OR user.in_group("mozilla-messaging-confidential")
+ OR user.in_group("mozilla-foundation-confidential") %]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>MoLegal</div>
+
+<p><strong>Welcome to MoLegal.</strong> For legal help please fill in the form below completely.</p>
+
+<p>Legal [% terms.bugs %] are only visible to the reporter, members of the legal team, and those on the
+CC list. This is necessary to maintain attorney-client privilege. Please do not add non-
+employees to the cc list.</p>
+
+<p><strong>All Submissions, And Information Provided In Response To This Request,
+Are Confidential And Subject To The Attorney-Client Privilege And Work Product Doctrine.</strong></p>
+
+<p>If you are requesting legal review of a new product or service, a new feature of an existing product
+ or service, or any type of contract, please go
+ <a href="[% urlbase FILTER none %]enter_bug.cgi?product=mozilla.org&format=moz-project-review">here</a>
+ to kick-off review of your project. If you are requesting another type of legal action, e.g patent analysis,
+ trademark misuse investigation, HR issue, or standards work, please use this form.</p>
+
+<form method="post" action="post_bug.cgi" id="legalRequestForm" enctype="multipart/form-data">
+ <input type="hidden" name="product" value="Legal">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="bug_severity" value="normal">
+ <input type="hidden" name="format" value="legal">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ [% IF user.in_group('canconfirm') %]
+ <input type="hidden" name="bug_status" value="NEW">
+ [% END %]
+
+<table>
+
+<tr>
+ <td align="right" width="170px"><strong>Request Type:</strong></td>
+ <td>
+ <select name="component">
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ [% " selected=\"selected\"" IF c.name == "General" %]>
+ [% c.name FILTER html -%]
+ </option>
+ [%- END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong>Goal:</strong>
+ </td>
+ <td colspan="3">
+ <em>Identify the company goal this request maps to.</em><br>
+ <input name="goal" id="goal" size="60" value="[% goal FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <td align="right">
+ <strong>Priority to your Team:</strong>
+ </td>
+ <td>
+ <select id="teampriority" name="teampriority">
+ <option value="High">High</option>
+ <option value="Medium">Medium</option>
+ <option value="Low" selected="selected">Low</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right">
+ <strong>Timeframe for Completion:</strong>
+ </td>
+ <td>
+ <select id="timeframe" name="timeframe">
+ <option value="2 days">2 days</option>
+ <option value="a week">a week</option>
+ <option value="2-4 weeks">2-4 weeks</option>
+ <option value="this will take a while, but please get started soon">
+ this will take a while, but please get started soon</option>
+ <option value="no rush" selected="selected">no rush</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong>Summary:</strong>
+ </td>
+ <td colspan="3">
+ <em>Include the name of the vendor, partner, product, or other identifier.</em><br>
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <td align="right">
+ <strong>CC&nbsp;(optional):</strong>
+ </td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong>Name of Other Party:</strong>
+ </td>
+ <td>
+ <em>If applicable, include full legal entity name, address, and any other relevant contact information.</em><br>
+ <textarea id="otherparty" name="otherparty" rows="3" cols="80"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td align="right">
+ <strong>Business Objective:</strong>
+ </td>
+ <td>
+ <input type="text" name="busobj" id="busobj" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong>Description:</strong>
+ </td>
+ <td colspan="3">
+ <em>Describe your question, what you want and/or provide any relevant deal terms, restrictions,<br>
+ or provisions that are applicable. Also provide context and background.</em><br>
+ <textarea id="comment" name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+</tr>
+
+<tr>
+ <td></td>
+ <td colspan=2><strong>Attachment (this is optional)</strong></td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong><label for="data">File:</label></strong>
+ </td>
+ <td>
+ <em>Enter the path to the file on your computer.</em><br>
+ <input type="file" id="data" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right" valign="top">
+ <strong><label for="description">Description:</label></strong>
+ </td>
+ <td>
+ <em>Describe the attachment briefly.</em><br>
+ <input type="text" id="description" name="description" size="60" maxlength="200">
+ </td>
+</tr>
+
+</table>
+
+<br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us. You will be notified by email of any progress made in resolving your request.</p>
+
+[% ELSE %]
+
+<p>Sorry, you do not have access to this page.</p>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-mdn.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mdn.html.tmpl
new file mode 100644
index 000000000..44f81abc8
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mdn.html.tmpl
@@ -0,0 +1,277 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_style = BLOCK %]
+strong.required:before {
+ content: "* ";
+ color: red;
+}
+#yui-history-iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 1px;
+ height: 1px;
+ visibility: hidden;
+}
+#advanced {
+ margin-top: 50px;
+}
+#advanced img {
+ vertical-align: middle;
+}
+#advanced a {
+ cursor: pointer;
+}
+[% END %]
+[% inline_javascript = BLOCK %]
+ var Dom = YAHOO.util.Dom;
+ var Event = YAHOO.util.Event;
+ var History = YAHOO.util.History;
+ var mdn = {
+ _initial_state: 'initial',
+ _current_state: 'initial',
+ _current_type: 'Bug',
+ _required_fields: {
+ 'Bug': {
+ 'bug_actions': 'Please enter some text for "What did you do?"',
+ 'bug_actual_results': 'Please enter some text for "What happened?"',
+ 'bug_expected_results': 'Please enter some text for "What should have happened?"',
+ },
+ 'Feature': {
+ 'feature_problem_solving': 'Please enter some text for "What problems would this solve?"',
+ 'feature_audience': 'Please enter some text for "Who would use this?"',
+ 'feature_interface': 'Please enter some text for "What would users see?"',
+ 'feature_process': 'Please enter some text for "What would users do? What would happen as a result?"',
+ },
+ 'Change': {
+ 'change_feature': 'Please enter some text for "What feature should be changed? Please provide the URL of the feature if possible"',
+ 'change_problem_solving': 'Please enter some text for "What problems would this solve?"',
+ 'change_audience': 'Please enter some text for "Who would use this?"',
+ 'change_interface': 'Please enter some text for "What would users see?"',
+ 'change_process': 'Please enter some text for "What would users do? What would happen as a result?"',
+ }
+ },
+ setState: function(state, request_type, no_set_history) {
+ if (state == 'detail') {
+ request_type = request_type || this._getRadioValueByClass('request_type');
+ request_type = request_type.toLowerCase();
+ if (request_type == 'bug') {
+ Dom.get('detail_header').innerHTML = '<h2>[% terms.Bug %] Report</h2>';
+ Dom.get('secure_type').innerHTML = 'report';
+ }
+ if (request_type == 'feature') {
+ Dom.get('detail_header').innerHTML = '<h2>Feature Request</h2>';
+ Dom.get('secure_type').innerHTML = 'request';
+ }
+ if (request_type == 'change') {
+ Dom.get('detail_header').innerHTML = '<h2>Change Request</h2>';
+ Dom.get('secure_type').innerHTML = 'request';
+ }
+ Dom.addClass('detail_' + this._current_type, 'bz_default_hidden');
+ Dom.removeClass('detail_' + request_type, 'bz_default_hidden');
+ this._current_type = request_type;
+ }
+ Dom.addClass(this._current_state + '_form', 'bz_default_hidden');
+ Dom.removeClass(state + '_form', 'bz_default_hidden');
+ this._current_state = state;
+ if (History && !no_set_history) {
+ History.navigate('h', state +
+ (request_type ? '|' + request_type : ''));
+ }
+ return true;
+ },
+ validateAndSubmit: function() {
+ var request_type = this._getRadioValueByClass('request_type');
+ var alert_text = '';
+ if (!isFilledOut('short_desc')) alert_text += 'Please enter a "Summary".\n';
+ for (require_type in this._required_fields) {
+ if (require_type == request_type) {
+ for (field in this._required_fields[require_type]) {
+ if (!isFilledOut(field))
+ alert_text += this._required_fields[require_type][field] + "\n";
+ }
+ }
+ }
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+ var whiteboard = Dom.get('status_whiteboard');
+ whiteboard.value = "[specification][type:" + request_type.toLowerCase() + "]";
+ return true;
+ },
+ _getRadioValueByClass: function(class_name) {
+ var elements = Dom.getElementsByClassName(class_name);
+ for (var i = 0, l = elements.length; i < l; i++) {
+ if (elements[i].checked) return elements[i].value;
+ }
+ },
+ init: function() {
+ var bookmarked_state = History.getBookmarkedState('h');
+ this._initial_state = bookmarked_state || 'initial';
+ try {
+ History.register('h', this._initial_state, mdn.onStateChange);
+ History.initialize('yui-history-field', 'yui-history-iframe');
+ History.onReady(function () {
+ mdn.onStateChange(History.getCurrentState('h'), true);
+ });
+ }
+ catch(e) {
+ console.log('error initializing history: ' + e);
+ History = false;
+ }
+ },
+ onStateChange: function(state, no_set_history) {
+ var state_data = state.split('|');
+ mdn.setState(state_data[0], state_data[1], no_set_history);
+ }
+ };
+ Event.on('show_detail', 'click', function() { mdn.setState('detail'); });
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Developer Network Feedback"
+ style = inline_style
+ javascript = inline_javascript
+ yui = [ 'history' ]
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js' ]
+%]
+
+<iframe id="yui-history-iframe" src="extensions/BMO/web/yui-history-iframe.txt"></iframe>
+<input id="yui-history-field" type="hidden">
+
+<h1>Mozilla Developer Network Feedback</h1>
+
+<form method="post" action="post_bug.cgi" enctype="multipart/form-data"
+ onSubmit="return mdn.validateAndSubmit();">
+ <input type="hidden" name="format" value="mdn">
+ <input type="hidden" name="product" value="Mozilla Developer Network">
+ <input type="hidden" name="component" value="General">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ <input type="hidden" name="status_whiteboard" id="status_whiteboard" value="">
+
+ <div id="initial_form">
+ <p>
+ <input type="radio" name="request_type" class="request_type"
+ id="request_type_bug" value="Bug" checked="checked">
+ <label for="request_type_bug">Report a [% terms.bug %]</label><br>
+ <input type="radio" name="request_type" class="request_type"
+ id="request_type_feature" value="Feature">
+ <label for="request_type_feature">Request a new feature</label><br>
+ <input type="radio" name="request_type" class="request_type"
+ id="request_type_change" value="Change">
+ <label for="request_type_change">Request a change to an existing feature</label><br>
+ <br>
+ <input id="show_detail" type="button" value="Next">
+ </p>
+ </div>
+
+ <div id="detail_form" class="bz_default_hidden">
+ <p id="detail_header"></p>
+
+ <p id="detail_summary">
+ <strong class="required">Summary</strong><br>
+ <input type="text" name="short_desc" id="short_desc" size="60">
+ </p>
+
+ <div id="detail_bug" class="bz_default_hidden">
+ <p>
+ <strong class="required">What did you do?</strong><br>
+ <textarea name="bug_actions" id="bug_actions" rows="5" cols="60">
+1.&nbsp;
+2.&nbsp;
+3.&nbsp;</textarea>
+ </p>
+ <p>
+ <strong class="required">What happened?</strong><br>
+ <textarea name="bug_actual_results" id="bug_actual_results" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What should have happened?</strong><br>
+ <textarea name="bug_expected_results" id="bug_expected_results" rows="5" cols="60"></textarea>
+ </p>
+ </div>
+
+ <div id="detail_feature" class="bz_default_hidden">
+ <p>
+ <strong class="required">What problems would this solve?</strong><br>
+ <textarea name="feature_problem_solving" id="feature_problem_solving" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">Who would use this?</strong><br>
+ <textarea name="feature_audience" id="feature_audience" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What would users see?</strong><br>
+ <textarea name="feature_interface" id="feature_interface" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What would users do? What would happen as a result?</strong><br>
+ <textarea name="feature_process" id="feature_process" rows="5" cols="60"></textarea>
+ </p>
+ </div>
+
+ <div id="detail_change" class="bz_default_hidden">
+ <p>
+ <strong class="required">What feature should be changed? Please provide the URL of the feature if possible.</strong><br>
+ <textarea name="change_feature" id="change_feature" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What problems would this solve?</strong><br>
+ <textarea name="change_problem_solving" id="change_problem_solving" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">Who would use this?</strong><br>
+ <textarea name="change_audience" id="change_audience" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What would users see?</strong><br>
+ <textarea name="change_interface" id="change_interface" rows="5" cols="60"></textarea>
+ </p>
+ <p>
+ <strong class="required">What would users do? What would happen as a result?</strong><br>
+ <textarea name="change_process" id="change_process" rows="5" cols="60"></textarea>
+ </p>
+ </div>
+
+ <p id="detail_description">
+ <strong>Is there anything else we should know?</strong><br>
+ <textarea name="description" id="description" rows="5" cols="60"></textarea>
+ </p>
+
+ <p id="detail_secure">
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+ <input type="checkbox" name="groups" id="groups" value="[% sec_group FILTER html %]">
+ <label for="groups"><strong>This <span id="secure_type">report</span> is about a problem
+ that is putting users at risk. It should be kept hidden from the public until it is
+ resolved.</strong></label>
+ </p>
+
+ <input type="submit" id="commit" value="Submit"></td>
+ </div>
+</form>
+
+<div id="advanced">
+ <a id="advanced_img" href="enter_bug.cgi?format=__standard__&product=Mozilla+Developer+Network">
+ <img src="extensions/BMO/web/images/advanced.png" width="16" height="16" border="0"></a>
+ <a id="advanced_link" href="enter_bug.cgi?format=__standard__&product=Mozilla+Developer+Network">
+ Switch to the advanced [% terms.bug %] entry form</a>
+</div>
+
+<script>
+ mdn.init();
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl
new file mode 100644
index 000000000..38c08c72f
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl
@@ -0,0 +1,177 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Discussion Forum"
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+ style = ".mandatory{color:red;font-size:80%;}"
+%]
+
+<script type="text/javascript">
+<!--
+ function trySubmit() {
+ var alert_text = "";
+
+ if (!isFilledOut('listName')) {
+ alert_text += "Please enter the list name\n";
+ }
+
+ if (!isValidEmail(document.getElementById('listAdmin').value)) {
+ alert_text += "Please enter a valid email address for the list administrator\n";
+ }
+
+ if (alert_text) {
+ alert(alert_text);
+ return false;
+ }
+
+ var listName = document.getElementById('listName').value;
+ document.getElementById('short_desc').value = "Discussion Forum: " + listName;
+
+ return true;
+ }
+// -->
+</script>
+
+<p>
+ <b>Create a Mozilla Discussion Forum</b><br>
+ This option gives you a Mozilla <a
+ href="https://www.mozilla.org/about/forums/">Discussion Forum</a>.
+ These are the normal mechanism for public discussion in the Mozilla
+ project. They are made up of a mailing list on
+ <b>lists.mozilla.org</b>, a newsgroup on <b>news.mozilla.org</b> and
+ a <b>Google Group</b> (which maintains the list archives), all linked
+ together. Users can add and remove themselves.
+</p>
+
+<div id="message">
+ <b>Note:</b>
+ You must use <a href="https://mozilla.service-now.com/"><b>Service Now</b></a>
+ to request a distribution list or a standard mailing list.
+</div>
+<br>
+
+<form method="post" action="post_bug.cgi" id="mozListRequestForm"
+ enctype="multipart/form-data" onSubmit="return trySubmit();">
+ <input type="hidden" id="format" name="format" value="mozlist">
+ <input type="hidden" id="product" name="product" value="mozilla.org">
+ <input type="hidden" id="rep_platform" name="rep_platform" value="All">
+ <input type="hidden" id="op_sys" name="op_sys" value="Other">
+ <input type="hidden" id="priority" name="priority" value="--">
+ <input type="hidden" id="version" name="version" value="other">
+ <input type="hidden" id="short_desc" name="short_desc" value="">
+ <input type="hidden" id="component" name="component" value="Discussion Forums">
+ <input type="hidden" id="bug_severity" name="bug_severity" value="normal">
+ <input type="hidden" id="token" name="token" value="[% token FILTER html %]">
+
+ <table>
+ <tr>
+ <th class="field_label">
+ <span class="mandatory" title="Required">*</span> List Name:
+ </th>
+ <td>
+ The desired name for the newsgroup. Should start with 'mozilla.' and fit somewhere
+ in the hierarchy described <a href="https://www.mozilla.org/about/forums/">here</a>.<br>
+ <input name="listName" id="listName" size="60" value="[% listName FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th class="field_label">
+ <span class="mandatory" title="Required">*</span> List Administrator:
+ </th>
+ <td>
+ <b>Note:</b>The list administrator is also initially considered to be the list moderator
+ and will be responsible for moderation tasks unless delegated to someone else. For
+ convenience, [% terms.Bugzilla %] user accounts will autocomplete but it does not have
+ to be a [% terms.Bugzilla %] account.<br>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "listAdmin"
+ name => "listAdmin"
+ value => ""
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+ <tr>
+ <td class="field_label">Short Description:</th>
+ <td>
+ This will be shown to users on the index of lists on the server.<br>
+ <input name="listShortDesc" id="listShortDesc" size="60" value="[% listShortDesc FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <td class="field_label">Long Description:</th>
+ <td>
+ This will be shown at the top of the list's listinfo page.<br>
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'listLongDesc'
+ id = 'listLongDesc'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = listLongDesc
+ %]
+ </td>
+ </tr>
+ <tr>
+ <th class="field_label">Additional Comments:</th>
+ <td>
+ Justification for the list, special instructions, etc.<br>
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = comment
+ %]
+ </td>
+ </tr>
+ <tr>
+ <th class="field_label">CC:</th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+ <tr>
+ <th class="field_label">URL:</th>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <td align="right">
+ <input type="checkbox" name="groups" id="group_35" value="infra">
+ </td>
+ <td>
+ <label for="group_35"><b>This is an internal issue which should not be publicly visible.</b></label>
+ </td>
+ </tr>
+ </table>
+
+ <input type="submit" id="commit" value="Submit Request">
+
+ <p>
+ Thanks for contacting us. You will be notified by email of any progress made
+ in resolving your request.
+ </p>
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
new file mode 100644
index 000000000..ad8216b47
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
@@ -0,0 +1,648 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # Shane H. W. Travis <travis@sedsystems.ca>
+ # Marc Schumann <wurblzap@gmail.com>
+ # Akamai Technologies <bugzilla-dev@akamai.com>
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ # Frédéric Buclin <LpSolit@gmail.com>
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+[% title = BLOCK %]Create a PR Request[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = title
+ style_urls = [ 'skins/standard/attachment.css' ]
+ javascript_urls = [ "js/attachment.js", "js/util.js",
+ "js/field.js", "js/TUI.js" ]
+ onload = 'set_assign_to();'
+ yui = [ 'autocomplete' ]
+%]
+
+<script type="text/javascript">
+<!--
+
+var initialowners = new Array([% product.components.size %]);
+var last_initialowner;
+var initialccs = new Array([% product.components.size %]);
+var components = new Array([% product.components.size %]);
+var comp_desc = new Array([% product.components.size %]);
+var flags = new Array([% product.components.size %]);
+[% IF Param("useqacontact") %]
+ var initialqacontacts = new Array([% product.components.size %]);
+ var last_initialqacontact;
+[% END %]
+[% count = 0 %]
+[%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ components[[% count %]] = "[% c.name FILTER js %]";
+ comp_desc[[% count %]] = "[% c.description FILTER html_light FILTER js %]";
+ initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]";
+ [% flag_list = [] %]
+ [% FOREACH f = c.flag_types(is_active=>1).bug %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ [% FOREACH f = c.flag_types(is_active=>1).attachment %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ flags[[% count %]] = [[% flag_list.join(",") FILTER js %]];
+ [% IF Param("useqacontact") %]
+ initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
+ [% END %]
+
+ [% SET initial_cc_list = [] %]
+ [% FOREACH cc_user = c.initial_cc %]
+ [% initial_cc_list.push(cc_user.login) %]
+ [% END %]
+ initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]";
+
+ [% count = count + 1 %]
+[%- END %]
+
+function set_assign_to() {
+ // Based on the selected component, fill the "Assign To:" field
+ // with the default component owner, and the "QA Contact:" field
+ // with the default QA Contact. It also selectively enables flags.
+ var form = document.Create;
+ var assigned_to = form.assigned_to.value;
+
+[% IF Param("useqacontact") %]
+ var qa_contact = form.qa_contact.value;
+[% END %]
+
+ var index = -1;
+ if (form.component.type == 'select-one') {
+ index = form.component.selectedIndex;
+ } else if (form.component.type == 'hidden') {
+ // Assume there is only one component in the list
+ index = 0;
+ }
+ if (index != -1) {
+ var owner = initialowners[index];
+ var component = components[index];
+ if (assigned_to == last_initialowner
+ || assigned_to == owner
+ || assigned_to == '') {
+ form.assigned_to.value = owner;
+ last_initialowner = owner;
+ }
+
+ document.getElementById('initial_cc').innerHTML = initialccs[index];
+ document.getElementById('comp_desc').innerHTML = comp_desc[index];
+
+ [% IF Param("useqacontact") %]
+ var contact = initialqacontacts[index];
+ if (qa_contact == last_initialqacontact
+ || qa_contact == contact
+ || qa_contact == '') {
+ form.qa_contact.value = contact;
+ last_initialqacontact = contact;
+ }
+ [% END %]
+
+ // First, we disable all flags. Then we re-enable those
+ // which are available for the selected component.
+ var inputElements = document.getElementsByTagName("select");
+ var inputElement, flagField;
+ for ( var i=0 ; i<inputElements.length ; i++ ) {
+ inputElement = inputElements.item(i);
+ if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) {
+ var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1");
+ inputElement.disabled = true;
+ // Also disable the requestee field, if it exists.
+ inputElement = document.getElementById("requestee_type-" + id);
+ if (inputElement) inputElement.disabled = true;
+ }
+ }
+ // Now enable flags available for the selected component.
+ for (var i = 0; i < flags[index].length; i++) {
+ flagField = document.getElementById("flag_type-" + flags[index][i]);
+ // Do not enable flags the user cannot set nor request.
+ if (flagField && flagField.options.length > 1) {
+ flagField.disabled = false;
+ // Re-enabling the requestee field depends on the status
+ // of the flag.
+ toggleRequesteeField(flagField, 1);
+ }
+ }
+ }
+}
+
+function fix_component() {
+ var form = document.Create;
+ var location = form.location.options[form.location.selectedIndex].value;
+ var fakecomp = form.fakecomp.options[form.fakecomp.selectedIndex].value;
+ var newcomp = location + " - " + fakecomp;
+ form.component.value = newcomp;
+ set_assign_to();
+}
+
+function handleWantsAttachment(wants_attachment) {
+ if (wants_attachment) {
+ document.getElementById('attachment_false').style.display = 'none';
+ document.getElementById('attachment_true').style.display = 'block';
+ }
+ else {
+ document.getElementById('attachment_false').style.display = 'block';
+ document.getElementById('attachment_true').style.display = 'none';
+ clearAttachmentFields();
+ }
+}
+
+
+TUI_alternates['expert_fields'] = 'Show Advanced Fields';
+// Hide the Advanced Fields by default, unless the user has a cookie
+// that specifies otherwise.
+TUI_hide_default('expert_fields');
+
+-->
+</script>
+
+[% IF user.in_group("mozilla-confidential") %]
+
+[% USE Bugzilla %]
+
+<form name="Create" id="Create" method="post" action="post_bug.cgi"
+ enctype="multipart/form-data">
+<input type="hidden" name="product" value="[% product.name FILTER html %]">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table cellspacing="4" cellpadding="2" border="0" style="background: url(extensions/BMO/web/images/presshat.png) top right no-repeat">
+<tbody>
+ <tr>
+ <td colspan="2">
+ <a id="expert_fields_controller" class="controller bz_default_hidden"
+ href="javascript:TUI_toggle_class('expert_fields')">Hide
+ Advanced Fields</a>
+ [%# Show the link if the browser supports JS %]
+ <script type="text/javascript">
+ YAHOO.util.Dom.removeClass('expert_fields_controller',
+ 'bz_default_hidden');
+ </script>
+ </td>
+ <td colspan="2">
+ (<span class="required_star">*</span> =
+ <span class="required_explanation">Required Field</span>)
+ </td>
+ </tr>
+
+ <tr>
+ <th>Product:</th>
+ <td width="10%">[% product.name FILTER html %]</td>
+
+ <th>Reporter:</th>
+ <td width="100%">[% user.login FILTER html %]</td>
+ </tr>
+
+ [%# We can't use the select block in these two cases for various reasons. %]
+[% matches = default.component_.matches('^(.*) - (.*)$') %]
+[% default.location = matches.0 %]
+[% default.fakecomp = matches.1 %]
+[% IF default.location == '' %]
+ [% default.location = 'US' %]
+[% END %]
+[% locations = [] %]
+[% fakecomps = [] %]
+[% FOREACH c = product.components %]
+ [% matches = c.name.match('^(.*) - (.*)$') %]
+ [% locations.push(matches.0) %]
+ [% fakecomps.push(matches.1) %]
+[% END %]
+[% locations = locations.unique %]
+[% fakecomps = fakecomps.unique %]
+ <tr>
+ <th class="required">
+ Location:
+ </th>
+ <td>
+
+ <select name="location" onchange="fix_component();" size="7">
+ [% FOREACH l = locations %]
+ <option value="[% l FILTER html %]" [% " selected=\"selected\"" IF l == default.location %]>
+ [% l FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ <select name="component" onchange="set_assign_to();" size="7"
+ aria-required="true" class="required" style="display: none;">
+ [%# Build the lists of assignees and QA contacts if "usemenuforusers" is enabled. %]
+ [% IF Param("usemenuforusers") %]
+ [% assignees_list = user.get_userlist.clone %]
+ [% qa_contacts_list = user.get_userlist.clone %]
+ [% END %]
+
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ [% " selected=\"selected\"" IF c.name == default.component_ %]>
+ [% c.name FILTER html -%]
+ </option>
+ [% IF Param("usemenuforusers") %]
+ [% INCLUDE build_userlist default_user = c.default_assignee,
+ userlist = assignees_list %]
+ [% INCLUDE build_userlist default_user = c.default_qa_contact,
+ userlist = qa_contacts_list %]
+ [% END %]
+ [%- END %]
+ </select>
+ </td>
+
+ </tr>
+ <tr>
+ <th>
+ Request type:
+ </th>
+ <td>
+
+ <select name="fakecomp" onchange="fix_component();" size="7">
+ [% FOREACH f = fakecomps %]
+ <option value="[% f FILTER html %]" [% " selected=\"selected\"" IF f == default.fakecomp %]>
+ [% f FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+ <td colspan="2">
+ [%# Enclose the fieldset in a nested table so that its width changes based
+ # on the length on the component description. %]
+ <table>
+ <tr>
+ <td>
+ <fieldset>
+ <legend>Request Description</legend>
+ <div id="comp_desc" class="comment">Select a request type to read its description.</div>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ <input type="hidden" name="bug_severity" value="[% default.bug_severity FILTER html %]">
+ <input type="hidden" name="rep_platform" value="[% default.rep_platform FILTER html %]">
+ <input type="hidden" name="op_sys" value="[% default.op_sys FILTER html %]">
+ <input type="hidden" name="version" value="unspecified">
+ </td>
+ </tr>
+</tbody>
+
+<tbody class="expert_fields">
+ <tr>
+ <td colspan="4">&nbsp;</td>
+ </tr>
+
+ <tr>
+[% IF bug_status.size <= 1 %]
+ <input type="hidden" name="bug_status"
+ value="[% default.bug_status FILTER html %]">
+ <th>Initial State:</th>
+ <td>[% display_value("bug_status", default.bug_status) FILTER html %]</td>
+[% ELSE %]
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.bug_status,
+ editable = (bug_status.size > 1), value = default.bug_status
+ override_legal_values = bug_status %]
+[% END %]
+
+ <td>&nbsp;</td>
+ [%# Calculate the number of rows we can use for flags %]
+ [% num_rows = 6 + (Param("useqacontact") ? 1 : 0) +
+ (user.is_timetracker ? 3 : 0) +
+ (Param("usebugaliases") ? 1 : 0)
+ %]
+
+ <td rowspan="[% num_rows FILTER html %]">
+ [% IF product.flag_types(is_active=>1).bug.size > 0 %]
+ [% display_flag_headers = 0 %]
+ [% any_flags_requesteeble = 0 %]
+
+ [% FOREACH flag_type = product.flag_types(is_active=>1).bug %]
+ [% display_flag_headers = 1 %]
+ [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %]
+ [% END %]
+
+ [% IF display_flag_headers %]
+ [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types(is_active=>1).bug
+ any_flags_requesteeble = any_flags_requesteeble
+ flag_table_id = "bug_flags"
+ %]
+ [% END %]
+ [% END %]
+ </td>
+ </tr>
+
+ <tr>
+ <th><a href="page.cgi?id=fields.html#assigned_to">Assign To</a>:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "assigned_to"
+ name => "assigned_to"
+ value => assigned_to
+ disabled => assigned_to_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => assignees_list
+ %]
+ <noscript>(Leave blank to assign to component's default assignee)</noscript>
+ </td>
+ </tr>
+
+[% IF Param("useqacontact") %]
+ <tr>
+ <th>QA Contact:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "qa_contact"
+ name => "qa_contact"
+ value => qa_contact
+ disabled => qa_contact_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => qa_contacts_list
+ %]
+ <noscript>(Leave blank to assign to default qa contact)</noscript>
+ </td>
+ </tr>
+[% END %]
+
+ <tr>
+ <th>CC:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ disabled => cc_disabled
+ size => 30
+ multiple => 5
+ %]
+ </td>
+ </tr>
+
+ <tr>
+ <th>Default CC:</th>
+ <td colspan="2">
+ <div id="initial_cc">
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="3">&nbsp;</td>
+ </tr>
+
+[% IF user.is_timetracker %]
+ <tr>
+ <th>Estimated Hours:</th>
+ <td colspan="2">
+ <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Deadline:</th>
+ <td colspan="2">
+ <input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]">
+ <small>(YYYY-MM-DD)</small>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="3">&nbsp;</td>
+ </tr>
+[% END %]
+
+[% IF Param("usebugaliases") %]
+ <tr>
+ <th>Alias:</th>
+ <td colspan="2">
+ <input name="alias" size="20" value="[% alias FILTER html %]">
+ </td>
+ </tr>
+[% END %]
+
+ <tr>
+ <th>URL:</th>
+ <td colspan="2">
+ <input name="bug_file_loc" size="40"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+</tbody>
+
+<tbody>
+
+ <tr>
+ <th class="required">Summary:</th>
+ <td colspan="3">
+ <input name="short_desc" size="70" value="[% short_desc FILTER html %]"
+ maxlength="255" spellcheck="true" aria-required="true"
+ class="required">
+ </td>
+ </tr>
+
+ <tr>
+ <th>Description:</th>
+ <td colspan="3">
+ [% defaultcontent = BLOCK %]
+ [% IF cloned_bug_id %]
++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id FILTER html %] +++
+
+
+ [% END %]
+ [%-# We are within a BLOCK. The comment will be correctly HTML-escaped
+ # by global/textarea.html.tmpl. So we must not escape the comment here. %]
+ [% comment FILTER none %]
+ [%- END %]
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = defaultcontent
+ %]
+ <br>
+ </td>
+ </tr>
+
+ [% IF user.is_insider %]
+ <tr class="expert_fields">
+ <th>&nbsp;</th>
+ <td colspan="3">
+ &nbsp;&nbsp;
+ <input type="checkbox" id="commentprivacy" name="commentprivacy"
+ [% " checked=\"checked\"" IF commentprivacy %]>
+ <label for="commentprivacy">
+ Make description private (visible only to members of the
+ <strong>[% Param('insidergroup') FILTER html %]</strong> group)
+ </label>
+ </td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Attachment:</th>
+ <td colspan="3">
+ <script type="text/javascript">
+ <!--
+ document.write( '<div id="attachment_false">'
+ + '<input type="button" value="Add an attachment" '
+ + 'onClick="handleWantsAttachment(true)"> '
+ + '<em style="display: none">This button has no '
+ + 'functionality for you because your browser does '
+ + 'not support CSS or does not use it.<\/em>'
+ + '<\/div>'
+ + '<div id="attachment_true" style="display: none">'
+ + '<input type="button" '
+ + 'value="Don\'t add an attachment " '
+ + 'onClick="handleWantsAttachment(false)">');
+ //-->
+ </script>
+ <fieldset>
+ <legend>Add an attachment</legend>
+ <table class="attachment_entry">
+ [% PROCESS attachment/createformcontents.html.tmpl
+ flag_types = product.flag_types(is_active=>1).attachment
+ any_flags_requesteeble = 1
+ flag_table_id ="attachment_flags" %]
+ </table>
+ </fieldset>
+ <script type="text/javascript">
+ <!--
+ document.write('<\/div>');
+ //-->
+ </script>
+ </td>
+ </tr>
+</tbody>
+
+<tbody class="expert_fields">
+ [% IF user.in_group('editbugs', product.id) %]
+ [% IF use_keywords %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.keywords, editable = 1,
+ value = keywords, desc_url = "describekeywords.cgi",
+ value_span = 3 %]
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Status Whiteboard:</th>
+ <td colspan="3">
+ <input id="status_whiteboard" name="status_whiteboard" size="70"
+ value="[% status_whiteboard FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Depends on:</th>
+ <td colspan="3">
+ <input name="dependson" accesskey="d" value="[% dependson FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Blocks:</th>
+ <td colspan="3">
+ <input name="blocked" accesskey="b" value="[% blocked FILTER html %]">
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody class="expert_fields">
+ [% IF product.groups_available.size %]
+ <tr>
+ <th>&nbsp;</th>
+ <td colspan="3">
+ <br>
+ <strong>
+ Only users in all of the selected groups can view this
+ [%+ terms.bug %]:
+ </strong>
+ <br>
+ <font size="-1">
+ (Leave all boxes unchecked to make this a public [% terms.bug %].)
+ </font>
+ <br>
+ <br>
+
+ <!-- Checkboxes -->
+ <input type="hidden" name="defined_groups" value="1">
+ [% FOREACH group = product.groups_available %]
+ <input type="checkbox" id="group_[% group.id FILTER html %]"
+ name="groups" value="[% group.name FILTER html %]"
+ [% ' checked="checked"' IF default.groups.contains(group.name)
+ OR group.is_default %]>
+ <label for="group_[% group.id FILTER html %]">
+ [%- group.description FILTER html_light %]</label><br>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody>
+ [%# Form controls for entering additional data about the bug being created. %]
+ [% Hook.process("form") %]
+
+ <tr>
+ <th>&nbsp;</th>
+ <td colspan="3">
+ <input type="submit" id="commit" value="Submit [% terms.Bug %]"
+ onclick="if (this.form.short_desc.value == '')
+ { alert('Please enter a summary sentence for this [% terms.bug %].');
+ return false; } return true;">
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <input type="submit" name="maketemplate" id="maketemplate"
+ value="Remember values as bookmarkable template"
+ class="expert_fields">
+ </td>
+ </tr>
+</tbody>
+ </table>
+ <input type="hidden" name="form_name" value="enter_bug">
+</form>
+
+[%# Links or content with more information about the bug being created. %]
+[% Hook.process("end") %]
+
+[% ELSE %]
+
+<p>Sorry, you do not have access to this page.</p>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK build_userlist %]
+ [% user_found = 0 %]
+ [% default_login = default_user.login %]
+ [% RETURN UNLESS default_login %]
+
+ [% FOREACH user = userlist %]
+ [% IF user.login == default_login %]
+ [% user_found = 1 %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+
+ [% userlist.push({login => default_login,
+ identity => default_user.identity,
+ visible => 1})
+ UNLESS user_found %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
new file mode 100644
index 000000000..e231cd9d5
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
@@ -0,0 +1,87 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skytt <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Powered by Mozilla Logo Requests"
+%]
+
+[% USE Bugzilla %]
+
+<p>If you are interested in using the <a href="http://www.mozilla.org/poweredby">Powered by Mozilla logo</a>,
+please provide some information about your application or product.</p>
+
+<p><strong>Please use this form for Powered by Mozilla logo requests only.</strong></p>
+
+<form method="post" action="post_bug.cgi" id="tmRequestForm">
+
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Trademark Permissions">
+ <input type="hidden" name="bug_severity" value="enhancement">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="assigned_to" value="dboswell@mozilla.com">
+ <input type="hidden" name="cc" value="liz@mozilla.com">
+ <input type="hidden" name="groups" value="marketing-private">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+ <table>
+ <tr>
+ <td align="right"><strong>Application or Product Name:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="Powered by Mozilla request for: [% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Comments&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+
+ </table>
+
+ <br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your
+ request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl
new file mode 100644
index 000000000..fd8d3c655
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl
@@ -0,0 +1,219 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Mozilla Corporation.
+ # Portions created by Mozilla are Copyright (C) 2008 Mozilla
+ # Corporation. All Rights Reserved.
+ #
+ # Contributor(s): Reed Loden <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation Mountain View Presentation Request"
+ javascript_urls = [ 'js/field.js', 'js/util.js' ]
+ style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }"
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Mountain View Presentation Request</div>
+
+<p><strong>Mountain View Presentation Request:</strong> Please use this form if you plan on hosting a presentation so that IT will be able to properly provide support. </p>
+
+<p>Process:</p>
+
+<ol><li>Complete and submit request below.</li>
+ <li>Your request will be reviewed and assigned to the appropriate person in IT.</li>
+</ol>
+
+<p>These requests will only be visible internally in all cases and only to the
+person who submitted the request and any persons designated in the CC line.</p>
+
+<script type="text/javascript">
+function trySubmit() {
+ var out = 'Topic: the_topic\r\nPresenter: the_presenter\r\nDate: the_date\r\nTime: the_time\r\nAudience: the_audience\r\nAir Mozilla: air_mozilla\r\nDial-in: dial_in\r\nArchive: to_archive\r\nMember of IT to help with A/V: it_help\r\nDescription: the_description';
+
+ var topic = document.getElementById('topic').value;
+ var presenter = document.getElementById('presenter').value;
+ var date = document.getElementById('date').value;
+ var time = document.getElementById('time_hour').value + ':' + document.getElementById('time_minute').value + document.getElementById('ampm').value;
+ var shortdesc = 'Mountain View Presentation Request - ' + topic + ' (' + date + ' ' + time + ')';
+ var airmozilla = document.getElementById('airmozilla').checked? 'yes' : 'no';
+ var dialin = document.getElementById('dialin').checked? 'yes' : 'no';
+ var archive = document.getElementById('archive').checked? 'yes' : 'no';
+ var ithelp = document.getElementById('ithelp').checked? 'yes' : 'no';
+
+ out = out.replace( /the_topic/, topic );
+ out = out.replace( /the_presenter/, presenter );
+ out = out.replace( /the_date/, date);
+ out = out.replace( /the_time/, time);
+ out = out.replace( /the_audience/, document.getElementById('audience').value );
+ out = out.replace( /air_mozilla/, airmozilla);
+ out = out.replace( /dial_in/, dialin);
+ out = out.replace( /the_description/, document.getElementById('description').value );
+ out = out.replace( /to_archive/, archive);
+ out = out.replace( /it_help/, ithelp);
+
+ document.getElementById('comment').value = out;
+ document.getElementById('short_desc').value = shortdesc;
+
+ return true;
+}
+
+</script>
+
+<form method="post" action="post_bug.cgi" id="presentationRequestForm" enctype="multipart/form-data"
+ onSubmit="return trySubmit();">
+
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="component" value="Server Operations: Desktop Issues">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="comment" id="comment" value="">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table>
+
+<tr>
+ <td align="right"><strong>Presenter:</strong></td>
+ <td>
+ <input type="text" name="presenter" id="presenter" value="" size="60" />
+ </td>
+
+</tr>
+
+<tr>
+ <td align="right"><strong>Topic:</strong></td>
+ <td>
+ <input type="text" name="topic" id="topic" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Date:</strong></td>
+ <td>
+ <input type="text" id="date" name="date" size="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date"
+ onclick="showCalendar('date')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_date"></div>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Start Time:</strong></td>
+ <td>
+ <select name="time_hour" id="time_hour">
+ <option value="12" selected>12</option>
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ </select>:<select name="time_minute" id="time_minute">
+ <option value="00" selected>00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+ </select>
+ <select name="ampm" id="ampm">
+ <option value="AM" selected>AM</option>
+ <option value="PM">PM</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Intended Audience:</strong></td>
+ <td>
+ <select name="audience" id="audience">
+ <option value="Public" selected>Open to Public</option>
+ <option value="Employees Only">Employees Only</option>
+ <option value="Interns">Interns</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Air Mozilla Broadcasting?</strong></td>
+ <td align="left"><input type="checkbox" name="airmozilla" id="airmozilla"></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Dial In?</strong></td>
+ <td align="left"><input type="checkbox" name="dialin" id="dialin"></td>
+</tr>
+
+<tr>
+<td align="right"><strong>Archive this?</strong></td>
+<td align="left"><input type="checkbox" name="archive" id="archive" value="yes"></td>
+</tr>
+
+
+<tr>
+<td align="right"><strong>Need IT to help run A/V?</strong></td>
+<td align="left"><input type="checkbox" name="ithelp" id="ithelp" value="yes" checked></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <th><label for="description">Description</label>:</th>
+ <td>
+ <em>Please briefly describe the presentation and any specific needs you might have.</em><br>
+
+ <textarea id="description" name="description" rows="10" cols="80"></textarea>
+ </td>
+</tr>
+
+ </table>
+
+ <br>
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+
+</p>
+
+<script type="text/javascript">
+ createCalendar('date');
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-privacy-data.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-privacy-data.html.tmpl
new file mode 100644
index 000000000..fbf3bed55
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-privacy-data.html.tmpl
@@ -0,0 +1,219 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% inline_style = BLOCK %]
+ #bug_form input[type=text], #bug_form input[type=file], #cc_autocomplete, #bug_form textarea {
+ width: 100%;
+ }
+[% END %]
+
+[% inline_js = BLOCK %]
+ function onSubmit() {
+ var error = '';
+ if (!isFilledOut('short_desc')) error += 'Please enter a summary.\n';
+ if (!isFilledOut('attachment')) error += 'Please attach the data set/representative sample.\n';
+ if (!isFilledOut('source')) error += 'Please enter the data source.\n';
+ if (!isFilledOut('data_desc')) error += 'Please enter the data description.\n';
+ if (!isFilledOut('release')) error += 'Please enter the parts of data you want released.\n';
+ if (!isFilledOut('why')) error += 'Please enter why you want to release this data.\n';
+ if (!isFilledOut('when')) error += 'Please enter when you would like to release this data.\n';
+
+ if (error) {
+ alert(error);
+ return false;
+ }
+
+ return true;
+ }
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Privacy - Data Release Proposal"
+ style = inline_style
+ style_urls = [ 'skins/standard/enter_bug.css' ]
+ javascript = inline_js
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/attachment.js', 'js/field.js', 'js/util.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+<h2>Privacy - Data Release Proposal</h2>
+
+<p>
+ Before filling out this form, please look at the
+ <a href="https://wiki.mozilla.org/Privacy/How_To/Deidentify" target="_blank">guide</a>
+ for releasing info about people.
+</p>
+
+<p>
+ All fields except for CC are required.
+</p>
+
+<form method="post" action="post_bug.cgi" id="bug_form" class="enter_bug_form"
+ enctype="multipart/form-data" onSubmit="return onSubmit()">
+<input type="hidden" name="format" value="privacy-data">
+<input type="hidden" name="product" value="Privacy">
+<input type="hidden" name="component" value="Data Release Proposal">
+<input type="hidden" name="rep_platform" value="All">
+<input type="hidden" name="op_sys" value="Other">
+<input type="hidden" name="priority" value="--">
+<input type="hidden" name="version" value="unspecified">
+<input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+<input type="hidden" name="comment" id="comment" value="">
+<input type="hidden" name="groups" id="groups" value="privacy">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table>
+
+<tr>
+ <th>
+ <label for="short_desc">Summary:</label>
+ </th>
+ <td>
+ <input type="text" name="short_desc" id="short_desc" value="" size="60">
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="cc">CC:</label>
+ </th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ <td>
+ <i>&nbsp;Optional</i>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="attachment">Data Set:</label>
+ </th>
+ <td>
+ <i>Please attach the data set, or a representative sample.</i>
+ <div>
+ <input type="file" id="attachment" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect">
+ <input type="hidden" name="description" value="Data Set">
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="source">Source:</label>
+ </th>
+ <td>
+ <i>Where does this data come from?</i>
+ <div>
+ <textarea name="source" id="source" rows="5" cols="40"></textarea>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="data_desc">Data Description:</label>
+ </th>
+ <td>
+ <i>What people and things does this data describe, and what fields does it contain?</i>
+ <div>
+ <textarea name="data_desc" id="data_desc" rows="5" cols="40"></textarea>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="release">Release:</label>
+ </th>
+ <td>
+ <i>What parts of this data do you want to release?</i>
+ <div>
+ <textarea name="release" id="release" rows="5" cols="40"></textarea>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="why">Why:</label>
+ </th>
+ <td>
+ <i>Why are we releasing this data, and what do we hope people will do with it?</i>
+ <div>
+ <textarea name="why" id="why" rows="5" cols="40"></textarea>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <th>
+ <label for="when">Release Time:</label>
+ </th>
+ <td>
+ <i>Is there a particular time by which you would like to release this data?</i>
+ <div>
+ <input type="text" name="when" id="when" value="" size="60">
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <td colspan="2">
+ Expect to discover that you've missed a few of things, so plan for a couple weeks to get them corrected.
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+</table>
+
+</form>
+
+<script type="text/javascript">
+function trySubmit() {
+ var topic = document.getElementById('topic').value;
+ var date = document.getElementById('date').value;
+ var time = document.getElementById('time_hour').value + ':' +
+ document.getElementById('time_minute').value +
+ document.getElementById('ampm').value + " " +
+ document.getElementById('time_zone').value;
+ var location = document.getElementById('location').value;
+ var shortdesc = 'Event - (' + date + ' ' + time + ') - ' + location + ' - ' + topic;
+ document.getElementById('short_desc').value = shortdesc;
+
+ // If intended audience is employees only, add mozilla-corporation-confidential group
+ var audience = document.getElementById('audience').value;
+ if (audience == 'Employees Only') {
+ var brownbagRequestForm = document.getElementById('brownbagRequestForm');
+ var groups = document.createElement('input');
+ groups.type = 'hidden';
+ groups.name = 'groups';
+ groups.value = 'mozilla-corporation-confidential';
+ brownbagRequestForm.appendChild(groups);
+ }
+
+ return true;
+}
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl
new file mode 100644
index 000000000..a75959abb
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl
@@ -0,0 +1,70 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation/Foundation Encryption Recovery Key"
+%]
+
+<p>Please complete the following information as you are encrypting your laptop.</p>
+
+<ul>
+ <li>The Recovery Key will be displayed during the encryption process
+ (<a href="https://mana.mozilla.org/wiki/display/INFRASEC/Desktop+Security#DesktopSecurity-DiskencryptionFileVault">more info</a>)
+ </li>
+ <li>The asset tag number is located on a sticker typically on the bottom of the device.</li>
+</ul>
+
+<form method="post" action="post_bug.cgi" id="recoveryKeyForm" enctype="multipart/form-data">
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="component" value="Server Operations: Desktop Issues">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="All">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <input type="hidden" name="bug_severity" value="normal">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+ <input type="hidden" name="groups" value="infra">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ <input type="hidden" name="cc" value="tfairfield@mozilla.com, ghuerta@mozilla.com">
+ <input type="hidden" name="short_desc" value="Encryption Recovery Key for [% user.name || user.login FILTER html %]">
+ <input type="hidden" name="format" value="recoverykey">
+ <table>
+ <tr>
+ <td align="right"><strong>Recovery Key:</strong></td>
+ <td>
+ <input name="recoverykey" size="60" value="[% recoverykey FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <td align="right"><strong>Asset Tag Number:</strong></td>
+ <td>
+ <input name="assettag" size="60" value="[% assettag FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><input type="submit" id="commit" value="Submit"></td>
+ </tr>
+ </table>
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl
new file mode 100644
index 000000000..3772120a0
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl
@@ -0,0 +1,751 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[%
+items = [
+ { id => '', name => 'splendidest gear', },
+ { id => '#157454S', name => 'very splendid package, men, s' },
+ { id => '#157454M', name => 'very splendid package, men, m' },
+ { id => '#157454L', name => 'very splendid package, men, l' },
+ { id => '#157454X', name => 'very splendid package, men, xl' },
+ { id => '#157452S', name => 'very splendid package, women, s' },
+ { id => '#157452M', name => 'very splendid package, women, m' },
+ { id => '#157452L', name => 'very splendid package, women, l' },
+ { id => '#157452X', name => 'very splendid package, women, xl' },
+ { id => '#157451S', name => 'most splendid package, s' },
+ { id => '#157451M', name => 'most splendid package, m ' },
+ { id => '#157451L', name => 'most splendid package, l' },
+ { id => '#157451X', name => 'most splendid package, xl' },
+ { id => '#155415S', name => 'sweatshirt, s' },
+ { id => '#155415M', name => 'sweatshirt, m' },
+ { id => '#155415L', name => 'sweatshirt, l' },
+ { id => '#155415X', name => 'sweatshirt, xl' },
+ { id => '#1554152', name => 'sweatshirt, 2x' },
+ { id => '#155749', name => 'rickshaw messenger bag' },
+ { id => '#155752', name => 'moleskine notebook (black)' },
+ { id => '', name => 'splendider gear', },
+ { id => '#155341S', name => 'unisex t, poppy, s' },
+ { id => '#155341M', name => 'unisex t, poppy, m' },
+ { id => '#155341L', name => 'unisex t, poppy, l' },
+ { id => '#155341X', name => 'unisex t, poppy, xl' },
+ { id => '#1553412', name => 'unisex t, poppy, 2x' },
+ { id => '#155344S', name => 'ladies t, poppy, s' },
+ { id => '#155344M', name => 'ladies t, poppy, m' },
+ { id => '#155344L', name => 'ladies t, poppy, l' },
+ { id => '#155342S', name => 'unisex t, navy, s' },
+ { id => '#155342M', name => 'unisex t, navy, m' },
+ { id => '#155342L', name => 'unisex t, navy, l' },
+ { id => '#155342X', name => 'unisex t, navy, xl' },
+ { id => '#1553422', name => 'unisex t, navy, 2x' },
+ { id => '#1553423', name => 'unisex t, navy, 3x' },
+ { id => '#155413S', name => 'ladies t, navy, s' },
+ { id => '#155413M', name => 'ladies t, navy, m' },
+ { id => '#155413L', name => 'ladies t, navy, l' },
+ { id => '#155413X', name => 'ladies t, navy, xl' },
+ { id => '#155343M', name => 'unisex t, lapis, m' },
+ { id => '#155343L', name => 'unisex t, lapis, l' },
+ { id => '#155343X', name => 'unisex t, lapis, xl' },
+ { id => '#155414S', name => 'ladies t, lapis, s' },
+ { id => '#155414M', name => 'ladies t, lapis, m' },
+ { id => '#155414L', name => 'ladies t, lapis, l' },
+ { id => '#155339', name => 'black cap w/tote' },
+ { id => '#155340', name => 'beanie' },
+ { id => '#155751', name => 'drawstring tote' },
+ { id => '#155758', name => 'glossy finish ceramic mug' },
+ { id => '', name => 'splendid gear', },
+ { id => '#155755', name => 'vertical laminated badge' },
+ { id => '#155754', name => 'lanyard w/bulldog clip' },
+ { id => '#155756', name => 'silicone wristband' },
+ { id => '#155753', name => '3" round stickers (single)' },
+ { id => '#155757', name => 'mozilla tattoos (pkg 50)' },
+]
+%]
+
+[%
+mozspaces = [
+ {
+ name => 'Mountain View',
+ address1 => 'Mozilla',
+ address2 => '650 Castro St., Suite 300',
+ city => 'Mountain View',
+ state => 'CA',
+ country => 'USA',
+ postcode => '94041-2072',
+ },
+ {
+ name => 'San Francisco',
+ address1 => 'Mozilla',
+ address2 => '2 Harrison Street, 7th Floor',
+ city => 'San Francisco',
+ state => 'CA',
+ country => 'USA',
+ postcode => '94105',
+ },
+ {
+ name => 'Toronto',
+ address1 => 'Mozilla Canada',
+ address2 => '366 Adelaide Street W, Suite 500',
+ city => 'Toronto',
+ state => 'Ontario',
+ country => 'Canada',
+ postcode => 'M5V 1R9',
+ },
+ {
+ name => 'Vancouver',
+ address1 => 'Mozilla Canada',
+ address2 => '163 West Hastings Street, Suite 209',
+ city => 'Vancouver',
+ state => 'BC',
+ country => 'Canada',
+ postcode => 'V6B 1H5',
+ },
+ {
+ name => 'London',
+ address1 => 'Mozilla London',
+ address2 => '101 St. Martin\'s Lane, 3rd Floor',
+ city => 'London',
+ state => 'Greater London',
+ country => 'UK',
+ postcode => 'WC2N 4AZ',
+ },
+ {
+ name => 'Paris',
+ address1 => 'Mozilla',
+ address2 => '28 Boulevard Poissonnière',
+ city => 'Paris',
+ state => 'Paris',
+ country => 'France',
+ postcode => '75009',
+ },
+ {
+ name => 'Berlin',
+ address1 => 'MZ Denmark ApS - Germany',
+ address2 => 'Rungestrasse 22 - 24',
+ city => 'Berlin',
+ state => 'Germany',
+ country => 'Germany',
+ postcode => '10179',
+ },
+]
+%]
+
+[% inline_style = BLOCK %]
+#gear_form th {
+ text-align: right;
+ font-weight: normal;
+}
+
+#gear_form .heading {
+ text-align: left;
+ font-weight: bold;
+ border-top: 2px dotted #969696;
+}
+
+.mandatory {
+ color: red;
+}
+[% END %]
+
+[% inline_javascript = BLOCK %]
+var Dom = YAHOO.util.Dom;
+var needed = {
+[% FOREACH item = items %]
+ [% NEXT UNLESS item.id %]
+ '[% item.id FILTER js %]': 0[% ',' UNLESS loop.last %]
+[% END %]
+};
+
+var gear = [
+[% FOREACH item = items %]
+ { id: '[% item.id FILTER js %]', name: '[% item.name FILTER js %]' }
+ [% ',' UNLESS loop.last %]
+[% END %]
+];
+
+var mozspaces = {
+[% FOREACH space = mozspaces %]
+ '[% space.name FILTER js %]': {
+ [% FOREACH key = space.keys.sort %]
+ '[% key FILTER js %]': '[% space.$key FILTER js %]'[% ',' UNLESS loop.last %]
+ [% END %]
+ }[% ',' UNLESS loop.last %]
+[% END %]
+};
+
+[%# implemented this way to allow for dynamic updating of mandatory fields #%]
+var fields = [
+ { id: 'firstname', mandatory: true },
+ { id: 'lastname', mandatory: true },
+ { id: 'email', mandatory: true },
+ { id: 'mozspace', mandatory: false },
+ { id: 'teamcode', mandatory: true },
+ { id: 'purpose', mandatory: true },
+ { id: 'purpose_other', mandatory: false },
+ { id: 'date_required', mandatory: false },
+ { id: 'items', mandatory: true },
+ { id: 'shiptofirstname', mandatory: true },
+ { id: 'shiptolastname', mandatory: true },
+ { id: 'shiptoemail', mandatory: true },
+ { id: 'shiptoaddress1', mandatory: true },
+ { id: 'shiptoaddress2', mandatory: false },
+ { id: 'shiptocity', mandatory: true },
+ { id: 'shiptostate', mandatory: true },
+ { id: 'shiptocountry', mandatory: true },
+ { id: 'shiptopostcode', mandatory: true },
+ { id: 'shiptophone', mandatory: true },
+ { id: 'shiptoidrut', mandatory: false },
+ { id: 'comment', mandatory: false }
+];
+
+function initFields() {
+ [%# find fields in the form, and update the fields array #%]
+ var rows = Dom.get('gear_form').getElementsByTagName('TR');
+ for (var i = 0, l = rows.length; i < l; i++) {
+ var row = rows[i];
+ var field = firstChild(row, 'INPUT') || firstChild(row, 'SELECT') || firstChild(row, 'TEXTAREA');
+ if (!field || field.type == 'submit') continue;
+ var id = field.id;
+ var label = firstChild(row, 'TH');
+ for (var j = 0, m = fields.length; j < m; j++) {
+ if (fields[j].id == id) {
+ fields[j].field = field;
+ fields[j].label = label;
+ fields[j].caption = label.textContent;
+ break;
+ }
+ }
+ }
+ createCalendar('date_required');
+}
+
+function tagMandatoryFields() {
+ [%# add or remove the "* mandatory" marker from fields #%]
+ for (var i = 0, l = fields.length; i < l; i++) {
+ var f = fields[i];
+ if (!f.label) continue;
+ var caption = f.caption;
+ if (f.mandatory)
+ caption = caption + '&nbsp;<span class="mandatory">*</span>';
+ f.label.innerHTML = caption;
+ }
+}
+
+function validateAndSubmit() {
+ var alert_text = '';
+ for(var i = 0, l = fields.length; i < l; i++) {
+ var f = fields[i];
+ if (f.mandatory && !isFilledOut(f.id))
+ if (f.field.nodeName == 'SELECT') {
+ alert_text += 'Please select the ' + f.caption + ".\n";
+ } else {
+ alert_text += 'Please enter the ' + f.caption + ".\n";
+ }
+ }
+ if (isFilledOut('email') && !isValidEmail(Dom.get('email').value))
+ alert_text += "Please enter a valid Email Address.\n";
+ if (isFilledOut('shiptoemail') && !isValidEmail(Dom.get('shiptoemail').value))
+ alert_text += "Please enter a valid Shipping Email Address.\n";
+
+ if (alert_text != '') {
+ alert(alert_text);
+ return false;
+ }
+
+ Dom.get('short_desc').value = 'Mozilla Gear - ' + Dom.get('firstname').value + ' ' + Dom.get('lastname').value;
+ return true;
+}
+
+function onPurposeChange() {
+ var value = Dom.get('purpose').value;
+ var other = Dom.get('purpose_other');
+
+ if (value == 'Event') {
+ getField('purpose_other').mandatory = true;
+ other.placeholder = 'link to wiki'
+ Dom.removeClass('purpose_other_row', 'bz_default_hidden');
+ Dom.addClass('recognition_row', 'bz_default_hidden');
+
+ } else if (value == 'Gear Space Stock') {
+ getField('purpose_other').mandatory = true;
+ other.placeholder = 'indicate space'
+ Dom.removeClass('purpose_other_row', 'bz_default_hidden');
+ Dom.addClass('recognition_row', 'bz_default_hidden');
+
+ } else if (value == 'Other') {
+ getField('purpose_other').mandatory = true;
+ other.placeholder = 'more information';
+ Dom.removeClass('purpose_other_row', 'bz_default_hidden');
+ Dom.addClass('recognition_row', 'bz_default_hidden');
+
+ } else if (value == 'Mozillian Recognition') {
+ getField('purpose_other').mandatory = false;
+ Dom.addClass('purpose_other_row', 'bz_default_hidden');
+ Dom.removeClass('recognition_row', 'bz_default_hidden');
+ onRecognitionChange();
+
+ } else {
+ getField('purpose_other').mandatory = false;
+ Dom.addClass('purpose_other_row', 'bz_default_hidden');
+ Dom.addClass('recognition_row', 'bz_default_hidden');
+ }
+
+ onRecognitionChange();
+}
+
+function onRecognitionChange() {
+ var mandatory = Dom.get('purpose').value != 'Mozillian Recognition'
+ || !Dom.get('recognition_shipping').checked;
+ getField('shiptoaddress1').mandatory = mandatory;
+ getField('shiptocity').mandatory = mandatory;
+ getField('shiptostate').mandatory = mandatory;
+ getField('shiptocountry').mandatory = mandatory;
+ getField('shiptopostcode').mandatory = mandatory;
+ getField('shiptophone').mandatory = mandatory && !Dom.get('shipto_mozspace').checked;
+ tagMandatoryFields();
+}
+
+function onMozSpaceChange() {
+ if (Dom.get('mozspace').value) {
+ Dom.removeClass('shipto_mozspace_container', 'bz_default_hidden');
+ } else {
+ Dom.addClass('shipto_mozspace_container', 'bz_default_hidden');
+ }
+ onShipToMozSpaceClick();
+}
+
+function onShipToMozSpaceClick() {
+ var address1 = address2 = city = state = country = postcode = '';
+ if (Dom.get('shipto_mozspace').checked) {
+ var space = Dom.get('mozspace').value;
+ address1 = mozspaces[space].address1;
+ address2 = mozspaces[space].address2;
+ city = mozspaces[space].city;
+ state = mozspaces[space].state;
+ country = mozspaces[space].country;
+ postcode = mozspaces[space].postcode;
+ }
+ Dom.get('shiptoaddress1').value = address1;
+ Dom.get('shiptoaddress2').value = address2;
+ Dom.get('shiptocity').value = city;
+ Dom.get('shiptostate').value = state;
+ Dom.get('shiptocountry').value = country;
+ Dom.get('shiptopostcode').value = postcode;
+ Dom.get('shiptophone').value = '';
+ Dom.get('shiptoidrut').value = '';
+ onRecognitionChange();
+}
+
+function firstChild(parent, name) {
+ var a = parent.getElementsByTagName(name);
+ return a.length == 0 ? false : a[0];
+}
+
+function getField(id) {
+ for(var i = 0, l = fields.length; i < l; i++) {
+ if (fields[i].id == id)
+ return fields[i];
+ }
+ return false;
+}
+
+function addGear() {
+ var quantity = parseInt(Dom.get('quantity').value, 10);
+ var id = Dom.get('add_gear').value;
+ if (!quantity || !id) return;
+ needed[id] += quantity;
+ showGear();
+}
+
+function removeGear(id) {
+ if (!id) return;
+ needed[id] = 0;
+ showGear();
+}
+
+function showGear() {
+ var html = '<table border="0" cellpadding="2" cellspacing="0">';
+ var text = '';
+ var count = 0;
+ for (var i = 0, l = gear.length; i < l; i++) {
+ var item = gear[i];
+ var id = item.id;
+ if (!id) continue;
+ if (!needed[id]) continue;
+ count += needed[id];
+ html += '<tr>' +
+ '<td>' + needed[id] + ' x&nbsp;</td>' +
+ '<td>' + YAHOO.lang.escapeHTML(item.name) + '</td>' +
+ '<td><button onclick="removeGear(\'' + id + '\');return false">Remove</button></td>' +
+ '</tr>';
+ text += needed[id] + ' x ' + id + ' ' + item.name + "\n";
+ }
+ if (!count)
+ html += '<tr><td><i>No gear selected.</i></td></tr>';
+ html += '</table>';
+ Dom.get('gear_container').innerHTML = html;
+ Dom.get('items').value = text;
+}
+
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Gear"
+ style = inline_style
+ javascript = inline_javascript
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js', 'js/util.js' ]
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+<h1>Mozilla Gear</h1>
+
+<p>
+ Want gear? Here's what to do:
+</p>
+<ul>
+ <li>
+ Follow the steps below and click Submit Request.
+ </li>
+ <li>
+ Requests are reviewed every Monday. If approved, we'll let you know. Then
+ your order will either be filled from your Mozilla space for pick-up or
+ sent to our gear partner, Staples, for processing and shipment. If it can't
+ be approved, we'll email you with details (or possibly ask for more
+ information).
+ </li>
+</ul>
+
+<p>
+ Check <a href="https://wiki.mozilla.org/GearStore" target="_blank">the gear
+ wiki</a> for more information about gear, including approved uses and the
+ list of available gear.
+</p>
+
+<p>
+ Gear requests for Rep-driven events and campaigns should continue to be
+ submitted through <a href="https://wiki.mozilla.org/ReMo/Tools_and_Resources"
+ target="_blank">their existing process</a>.
+</p>
+
+<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+ <input type="hidden" name="format" value="swag">
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Swag Requests">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-engagement">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="gear_form">
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+<tr>
+ <th class="heading" colspan="2">Tell Us What You Want</th>
+</tr>
+
+<tr>
+ <th>Purpose of Gear</th>
+ <td>
+ <select name="purpose" id="purpose" onchange="onPurposeChange()">
+ <option value="">Please select..</option>
+ <option value="Campaign">Campaign</option>
+ <option value="Event">Event</option>
+ <option value="Gear Space Stock">Gear Space Stock</option>
+ <option value="Mozillian Recognition">Mozillian Recognition</option>
+ <option value="Onboarding">Onboarding</option>
+ <option value="Press">Press</option>
+ <option value="Recruiting">Recruiting</option>
+ <option value="VIP">VIP</option>
+ <option value="Other">Other</option>
+ </select>
+ </td>
+</tr>
+
+<tr id="purpose_other_row" class="bz_default_hidden">
+ <th>Purpose Text</th>
+ <td>
+ <input name="purpose_other" id="purpose_other" size="50">
+ </td>
+</tr>
+
+<tr id="recognition_row" class="bz_default_hidden">
+ <th>&nbsp;</th>
+ <td>
+ <input type="checkbox" name="recognition_shipping" id="recognition_shipping" value="Yes"
+ onclick="onRecognitionChange()">
+ <label for="recognition_shipping">
+ This [% terms.bug %] needs recipient shipping information
+ </label><br>
+ <input type="checkbox" name="recognition_sizing" id="recognition_sizing" value="Yes">
+ <label for="recognition_sizing">
+ This [% terms.bug %] needs recipient size information
+ </label><br>
+ </td>
+</tr>
+
+<tr>
+ <th>Date Required</th>
+ <td>
+ <input name="date_required" id="date_required" size="25"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date_required"
+ onclick="showCalendar('date_required')"><span>cal</span></button>
+ <div id="con_calendar_date_required"></div>
+ </td>
+</tr>
+
+<tr>
+ <th>Gear Needed</th>
+ <td>
+ <input type="hidden" name="items" id="items" value="">
+ <a href="https://wiki.mozilla.org/GearStore/Gearavailable" target="_blank">
+ View the current inventory</a>, then add your selection(s):<br>
+
+ <input type="text" size="2" id="quantity" value="1"
+ onblur="this.value = parseInt(this.value, 10) ? Math.floor(parseInt(this.value, 10)) : 1">
+ <select id="add_gear">
+ <option value="">Please select..</option>
+ [% first_group = 1 %]
+ [% FOREACH item = items %]
+ [% IF item.id == "" %]
+ [% "</optgroup>" UNLESS first_group %]
+ [% first_group = 0 %]
+ <optgroup label="[% item.name FILTER html %]">
+ [% ELSE %]
+ <option value="[% item.id FILTER html %]">[% item.name FILTER html %]</option>
+ [% END %]
+ [% END %]
+ [% "</optgroup>" UNLESS first_group %]
+ </select>
+ <button onclick="addGear();return false">Add</button>
+ <br>
+
+ <div id="gear_container"></div>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+<tr>
+ <th class="heading" colspan="2">Tell Us About You</th>
+</tr>
+
+<tr>
+ <th>First Name</th>
+ <td><input name="firsrname" id="firstname" size="50" maxlength="30"></td>
+</tr>
+
+<tr>
+ <th>Last Name</th>
+ <td><input name="lastname" id="lastname" size="50" maxlength="30"></td>
+</tr>
+
+<tr>
+ <th>Email Address</th>
+ <td><input name="email" id="email" size="50" maxlength="50"></td>
+</tr>
+
+<tr>
+ <th>My Mozilla Space</th>
+ <td>
+ <select name="mozspace" id="mozspace" onchange="onMozSpaceChange()">
+ <option value="">Please select..</option>
+ [% FOREACH space = mozspaces %]
+ <option value="[% space.name FILTER html %]">[% space.name FILTER html %]</option>
+ [% END %]
+ </select>
+ <i>(if applicable)</i>
+ <div id="shipto_mozspace_container" class="bz_default_hidden">
+ <input type="checkbox" id="shipto_mozspace" onclick="onShipToMozSpaceClick()">
+ <label for="shipto_mozspace">Ship to this address</label>
+ </div>
+</tr>
+
+<tr>
+ <th>Team + Department Code</th>
+ <td>
+ <select name="teamcode" id="teamcode">
+ <option value="">Please select..</option>
+ <option value="Applications (350)">Applications (350)</option>
+ <option value="Business Affairs (110)">Business Affairs (110)</option>
+ <option value="Engagement Brand Management (240)">Engagement Brand Management (240)</option>
+ <option value="Engagement Contributor (230)">Engagement Contributor (230)</option>
+ <option value="Engagement General (200)">Engagement General (200)</option>
+ <option value="Engagement PR (220)">Engagement PR (220)</option>
+ <option value="Engagement Product Mktg (210)">Engagement Product Mktg (210)</option>
+ <option value="Engagement Product Strategy (250)">Engagement Product Strategy (250)</option>
+ <option value="Engagement User (232)">Engagement User (232)</option>
+ <option value="Engagement Websites &amp; Developer (235)">Engagement Websites &amp; Developer (235)</option>
+ <option value="Engr B2G (720)">Engr B2G (720)</option>
+ <option value="Engr Development Tools &amp; Auto (769)">Engr Development Tools &amp; Auto (769)</option>
+ <option value="Engr Firefox (770)">Engr Firefox (770)</option>
+ <option value="Engr Firefox Dev Tools (775)">Engr Firefox Dev Tools (775)</option>
+ <option value="Engr General Admin (700)">Engr General Admin (700)</option>
+ <option value="Engr Jetpack (780)">Engr Jetpack (780)</option>
+ <option value="Engr Localization - L10N (740)">Engr Localization - L10N (740)</option>
+ <option value="Engr Ops Build &amp; Release (440)">Engr Ops Build &amp; Release (440)</option>
+ <option value="Engr Ops Network &amp; IT (410)">Engr Ops Network &amp; IT (410)</option>
+ <option value="Engr Ops Stats &amp; Metrics (420)">Engr Ops Stats &amp; Metrics (420)</option>
+ <option value="Engr Ops Support/SUMO (450)">Engr Ops Support/SUMO (450)</option>
+ <option value="Engr Ops Weave &amp; Services (460)">Engr Ops Weave &amp; Services (460)</option>
+ <option value="Engr Ops Web Dev (430)">Engr Ops Web Dev (430)</option>
+ <option value="Engr Platform Content (810)">Engr Platform Content (810)</option>
+ <option value="Engr Platform General (800)">Engr Platform General (800)</option>
+ <option value="Engr Platform Graphics (820)">Engr Platform Graphics (820)</option>
+ <option value="Engr Platform Integration (880)">Engr Platform Integration (880)</option>
+ <option value="Engr Platform JS (830)">Engr Platform JS (830)</option>
+ <option value="Engr Platform Layout (840)">Engr Platform Layout (840)</option>
+ <option value="Engr Platform Network (855)">Engr Platform Network (855)</option>
+ <option value="Engr Platform Performance (870)">Engr Platform Performance (870)</option>
+ <option value="Engr Platform Stability Plugins (850)">Engr Platform Stability Plugins (850)</option>
+ <option value="Engr Project Mgmt (710)">Engr Project Mgmt (710)</option>
+ <option value="Engr QA Automation (760)">Engr QA Automation (760)</option>
+ <option value="Engr QA Browser Technologies (767)">Engr QA Browser Technologies (767)</option>
+ <option value="Engr QA Firefox Desktop (755)">Engr QA Firefox Desktop (755)</option>
+ <option value="Engr QA Services (750)">Engr QA Services (750)</option>
+ <option value="Engr QA Web (765)">Engr QA Web (765)</option>
+ <option value="Engr Research (860)">Engr Research (860)</option>
+ <option value="Engr Security (730)">Engr Security (730)</option>
+ <option value="Facility (150)">Facility (150)</option>
+ <option value="Finance (120)">Finance (120)</option>
+ <option value="G&amp;A (100)">G&amp;A (100)</option>
+ <option value="Innovations (300)">Innovations (300)</option>
+ <option value="Mobile (600)">Mobile (600)</option>
+ <option value="Mobile UI (610)">Mobile UI (610)</option>
+ <option value="Pancake (530)">Pancake (530)</option>
+ <option value="People (140)">People (140)</option>
+ <option value="People Ops (130)">People Ops (130)</option>
+ <option value="Product Add-Ons (550)">Product Add-Ons (550)</option>
+ <option value="Product UX (510)">Product UX (510)</option>
+ <option value="Products General (500)">Products General (500)</option>
+ <option value="Products User Research (520)">Products User Research (520)</option>
+ <option value="Security Assurance (470)">Security Assurance (470)</option>
+ <option value="Thunderbird (320)">Thunderbird (320)</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+<tr>
+ <th class="heading" colspan="2">Tell Us Where To Send It</th>
+</tr>
+
+<tr>
+ <td colspan="2">
+ Please be aware that shipping can cost as much as, if not more than, your
+ item. And, items shipped internationally incur customs fees that can be
+ 100%+ the cost of the package. When possible, requests will be filled from
+ gear at your Mozilla space.
+ </td>
+</tr>
+
+<tr>
+ <th>First Name</th>
+ <td><input name="shiptofirstname" id="shiptofirstname" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Last Name</th>
+ <td><input name="shiptolastname" id="shiptolastname" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Email Address</th>
+ <td><input name="shiptoemail" id="shiptoemail" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Address</th>
+ <td><input name="shiptoaddress1" id="shiptoaddress1" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Address 2</th>
+ <td><input name="shiptoaddress2" id="shiptoaddress2" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>City</th>
+ <td><input name="shiptocity" id="shiptocity" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>State</th>
+ <td><input name="shiptostate" id="shiptostate" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Country</th>
+ <td><input name="shiptocountry" id="shiptocountry" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Postal Code</th>
+ <td><input name="shiptopostcode" id="shiptopostcode" size="50" maxlength="50"></td>
+</tr>
+<tr>
+ <th>Recipient Telephone</th>
+ <td>
+ <input name="shiptophone" id="shiptophone" size="50" maxlength="50">
+ <i>(include country code if outside of the US)</i>
+ </td>
+</tr>
+<tr>
+ <th>Personal ID/RUT</th>
+ <td>
+ <input name="shiptoidrut" id="shiptoidrut" size="50" maxlength="50">
+ <i>(if your country requires this)</i>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+<tr>
+ <th class="heading" colspan="2">Tell Us Anything Else</th>
+</tr>
+
+<tr>
+ <th>Additional Comments</th>
+ <td><textarea id="comment" name="comment" rows="5" cols="50"></textarea></td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td><input type="submit" id="commit" value="Submit Request"></td>
+</tr>
+
+</table>
+</form>
+
+<p>
+ <span class="mandatory">*</span> Required Field
+</p>
+
+<p>
+ Requests will only be visible to the person who submitted it, authorized
+ members of the Mozilla Engagement team, and our Staples Customer Service rep.
+ We do this to help protect the personal identifying information in this [% terms.bugs %].
+</p>
+
+<script>
+ initFields();
+ onPurposeChange();
+ tagMandatoryFields();
+ showGear();
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl
new file mode 100644
index 000000000..977ad00d4
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl
@@ -0,0 +1,87 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Trademark Usage Requests"
+%]
+
+[% USE Bugzilla %]
+
+<p>
+ If, after reading
+ <a href="http://www.mozilla.org/foundation/trademarks/">the trademark policy
+ documents</a>, you know you need permission to use a certain trademark, this
+ is the place to be.
+</p>
+
+<p><strong>Please use this form for trademark requests only!</strong></p>
+
+<form method="post" action="post_bug.cgi" id="tmRequestForm">
+
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Trademark Permissions">
+ <input type="hidden" name="bug_severity" value="enhancement">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="priority" value="P3">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="groups" value="marketing-private">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+ <table>
+ <tr>
+ <td align="right"><strong>Summary:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Description:</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+ </table>
+
+ <br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your
+ request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl
new file mode 100644
index 000000000..d14cca810
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl
@@ -0,0 +1,800 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # Shane H. W. Travis <travis@sedsystems.ca>
+ # Marc Schumann <wurblzap@gmail.com>
+ # Akamai Technologies <bugzilla-dev@akamai.com>
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ # Frédéric Buclin <LpSolit@gmail.com>
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+[% title = BLOCK %]Enter [% terms.Bug %]: [% product.name FILTER html %][% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = title
+ yui = [ 'autocomplete', 'calendar', 'datatable', 'button' ]
+ style_urls = [ 'skins/standard/attachment.css',
+ 'skins/standard/enter_bug.css',
+ 'skins/custom/create_bug.css' ]
+ javascript_urls = [ "js/attachment.js", "js/util.js",
+ "js/field.js", "js/TUI.js", "js/bug.js",
+ "js/create_bug.js" ]
+ onload = "init();"
+%]
+
+<script type="text/javascript">
+<!--
+
+function init() {
+ set_assign_to();
+ hideElementById('attachment_true');
+ showElementById('attachment_false');
+ showElementById('btn_no_attachment');
+ initCrashSignatureField();
+ init_take_handler('[% user.login FILTER js %]');
+}
+
+function initCrashSignatureField() {
+ var el = document.getElementById('cf_crash_signature');
+ if (!el) return;
+ [% IF cf_crash_signature.length %]
+ YAHOO.util.Dom.addClass('cf_crash_signature_container', 'bz_default_hidden');
+ [% ELSE %]
+ hideEditableField('cf_crash_signature_container','cf_crash_signature_input',
+ 'cf_crash_signature_action', 'cf_crash_signature');
+ [% END %]
+}
+
+var initialowners = new Array();
+var last_initialowner;
+var initialccs = new Array();
+var components = new Array();
+var comp_desc = new Array();
+var flags = new Array();
+[% IF Param("useqacontact") %]
+ var initialqacontacts = new Array([% product.components.size %]);
+ var last_initialqacontact;
+[% END %]
+[% count = 0 %]
+[%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ [% NEXT IF c.name != 'WinQual Reports' %]
+ components[[% count %]] = "[% c.name FILTER js %]";
+ comp_desc[[% count %]] = "[% c.description FILTER html_light FILTER js %]";
+ initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]";
+ [% flag_list = [] %]
+ [% FOREACH f = c.flag_types(is_active=>1).bug %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ [% FOREACH f = c.flag_types(is_active=>1).attachment %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ flags[[% count %]] = [[% flag_list.join(",") FILTER js %]];
+ [% IF Param("useqacontact") %]
+ initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
+ [% END %]
+
+ [% SET initial_cc_list = [] %]
+ [% FOREACH cc_user = c.initial_cc %]
+ [% initial_cc_list.push(cc_user.login) %]
+ [% END %]
+ initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]";
+
+ [% count = count + 1 %]
+[%- END %]
+
+function set_assign_to() {
+ // Based on the selected component, fill the "Assign To:" field
+ // with the default component owner, and the "QA Contact:" field
+ // with the default QA Contact. It also selectively enables flags.
+ var form = document.Create;
+ var assigned_to = form.assigned_to.value;
+
+[% IF Param("useqacontact") %]
+ var qa_contact = form.qa_contact.value;
+[% END %]
+
+ var index = -1;
+ if (form.component.type == 'select-one') {
+ index = form.component.selectedIndex;
+ } else if (form.component.type == 'hidden') {
+ // Assume there is only one component in the list
+ index = 0;
+ }
+ if (index != -1) {
+ var owner = initialowners[index];
+ var component = components[index];
+ if (assigned_to == last_initialowner
+ || assigned_to == owner
+ || assigned_to == '') {
+ form.assigned_to.value = owner;
+ last_initialowner = owner;
+ }
+
+ document.getElementById('initial_cc').innerHTML = initialccs[index];
+ document.getElementById('comp_desc').innerHTML = comp_desc[index];
+
+ if (initialccs[index]) {
+ showElementById('initial_cc_label');
+ showElementById('initial_cc');
+ } else {
+ hideElementById('initial_cc_label');
+ hideElementById('initial_cc');
+ }
+
+ [% IF Param("useqacontact") %]
+ var contact = initialqacontacts[index];
+ if (qa_contact == last_initialqacontact
+ || qa_contact == contact
+ || qa_contact == '') {
+ form.qa_contact.value = contact;
+ last_initialqacontact = contact;
+ }
+ [% END %]
+
+ // First, we disable all flags. Then we re-enable those
+ // which are available for the selected component.
+ var inputElements = document.getElementsByTagName("select");
+ var inputElement, flagField;
+ for ( var i=0 ; i<inputElements.length ; i++ ) {
+ inputElement = inputElements.item(i);
+ if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) {
+ var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1");
+ inputElement.disabled = true;
+ // Also hide the requestee field, if it exists.
+ inputElement = document.getElementById("requestee_type-" + id);
+ if (inputElement)
+ YAHOO.util.Dom.addClass(inputElement.parentNode, 'bz_default_hidden');
+ }
+ }
+ // Now enable flags available for the selected component.
+ for (var i = 0; i < flags[index].length; i++) {
+ flagField = document.getElementById("flag_type-" + flags[index][i]);
+ // Do not enable flags the user cannot set nor request.
+ if (flagField && flagField.options.length > 1) {
+ flagField.disabled = false;
+ // Re-enabling the requestee field depends on the status
+ // of the flag.
+ toggleRequesteeField(flagField, 1);
+ }
+ }
+ }
+}
+
+var status_comment_required = new Array();
+[% FOREACH status = bug_status %]
+ status_comment_required['[% status.name FILTER js %]'] =
+ [% status.comment_required_on_change_from() ? 'true' : 'false' %]
+[% END %]
+
+TUI_alternates['expert_fields'] = 'Show Advanced Fields';
+// Hide the Advanced Fields by default, unless the user has a cookie
+// that specifies otherwise.
+TUI_hide_default('expert_fields');
+
+-->
+</script>
+
+<form name="Create" id="Create" method="post" action="post_bug.cgi"
+ class="enter_bug_form" enctype="multipart/form-data"
+ onsubmit="return validateEnterBug(this)">
+ <input type="hidden" name="product" value="Firefox">
+ <input type="hidden" name="component" value="WinQual Reports">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ <input type="hidden" name="groups" value="winqual-data">
+
+<table>
+<tbody>
+ <tr>
+ <td colspan="4">
+ [%# Migration note: The following file corresponds to the old Param
+ # 'entryheaderhtml'
+ #%]
+ [% PROCESS 'bug/create/user-message.html.tmpl' %]
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2">
+ <input type="button" id="expert_fields_controller"
+ value="Hide Advanced Fields" onClick="toggleAdvancedFields()">
+ [%# Show the link if the browser supports JS %]
+ <script type="text/javascript">
+ YAHOO.util.Dom.removeClass('expert_fields_controller',
+ 'bz_default_hidden');
+ </script>
+ </td>
+ <td colspan="2">
+ (<span class="required_star">*</span> =
+ <span class="required_explanation">Required Field</span>)
+ </td>
+ </tr>
+
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.product, editable = 0,
+ value = product.name %]
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.reporter, editable = 0,
+ value = user.login %]
+ </tr>
+
+ [%# We can't use the select block in these two cases for various reasons. %]
+ <tr>
+ [% component_desc_url = BLOCK -%]
+ describecomponents.cgi?product=[% product.name FILTER uri %]
+ [% END %]
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.component editable = 1
+ desc_url = component_desc_url
+ %]
+ <td id="field_container_component">
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.component, editable = 0,
+ value = "WinQual Reports", no_tds = 1 %]
+ <script type="text/javascript">
+ <!--
+ [%+ INCLUDE "bug/field-events.js.tmpl"
+ field = bug_fields.component %]
+ YAHOO.util.Event.onDOMReady(set_assign_to);
+ //-->
+ </script>
+ </td>
+
+ <td colspan="2" id="comp_desc_container">
+ [%# Enclose the fieldset in a nested table so that its width changes based
+ # on the length on the component description. %]
+ <table>
+ <tr>
+ <td>
+ <fieldset>
+ <legend>Component Description</legend>
+ <div id="comp_desc" class="comment"></div>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.version editable = 1 rowspan = 3
+ %]
+ <td rowspan="3">
+ <select name="version" id="version" size="5">
+ [%- FOREACH v = version %]
+ [% NEXT IF NOT v.is_active %]
+ <option value="[% v.name FILTER html %]"
+ [% ' selected="selected"' IF v.name == default.version %]>[% v.name FILTER html -%]
+ </option>
+ [%- END %]
+ </select>
+ </td>
+
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.bug_severity, editable = 1,
+ value = default.bug_severity %]
+ </tr>
+
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.rep_platform, editable = 1,
+ value = default.rep_platform %]
+ </tr>
+
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.op_sys, editable = 1,
+ value = default.op_sys %]
+ </tr>
+ [% IF !Param('defaultplatform') || !Param('defaultopsys') %]
+ <tr>
+ <th colspan="3">&nbsp;</th>
+ <td id="os_guess_note" class="comment">
+ <div>We've made a guess at your
+ [% IF Param('defaultplatform') %]
+ operating system. Please check it
+ [% ELSIF Param('defaultopsys') %]
+ platform. Please check it
+ [% ELSE %]
+ operating system and platform. Please check them
+ [% END %]
+ and make any corrections if necessary.</div>
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody class="expert_fields">
+ <tr>
+ [% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %]
+ [% INCLUDE select field = bug_fields.target_milestone %]
+ [% ELSE %]
+ <td colspan="2">&nbsp;</td>
+ [% END %]
+
+ [% IF Param('letsubmitterchoosepriority') %]
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.priority, editable = 1,
+ value = default.priority %]
+ [% ELSE %]
+ <td colspan="2">&nbsp;</td>
+ [% END %]
+ </tr>
+</tbody>
+
+<tbody class="expert_fields">
+ <tr>
+ <td colspan="4">&nbsp;</td>
+ </tr>
+
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.bug_status,
+ editable = (bug_status.size > 1), value = default.bug_status
+ override_legal_values = bug_status %]
+ </tr>
+
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.assigned_to editable = 1
+ %]
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "assigned_to"
+ name => "assigned_to"
+ value => assigned_to
+ disabled => assigned_to_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => assignees_list
+ %]
+ [% UNLESS assigned_to_disabled %]
+ <span id="take_bug">
+ &nbsp;(<a title="Assign to yourself" href="#"
+ onclick="return take_bug('[% user.login FILTER js %]')">take</a>)
+ </span>
+ [% END %]
+ <noscript>(Leave blank to assign to component's default assignee)</noscript>
+ </td>
+
+[% IF Param("useqacontact") %]
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.qa_contact editable = 1
+ %]
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "qa_contact"
+ name => "qa_contact"
+ value => qa_contact
+ disabled => qa_contact_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => qa_contacts_list
+ %]
+ <noscript>(Leave blank to assign to default qa contact)</noscript>
+ </td>
+ </tr>
+[% END %]
+
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.cc editable = 1
+ %]
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ disabled => cc_disabled
+ size => 30
+ multiple => 5
+ %]
+ </td>
+ <th>
+ <span id="initial_cc_label" class="bz_default_hidden">
+ Default [% field_descs.cc FILTER html %]:
+ </span>
+ </th>
+ <td>
+ <span id="initial_cc"></span>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="3">&nbsp;</td>
+ </tr>
+
+[% IF Param("usebugaliases") %]
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.alias editable = 1
+ %]
+ <td colspan="2">
+ <input name="alias" size="20" value="[% alias FILTER html %]">
+ </td>
+ </tr>
+[% END %]
+</tbody>
+
+<tbody>
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.short_desc editable = 1
+ %]
+ <td colspan="3" class="field_value">
+ <input name="short_desc" size="70" value="[% short_desc FILTER html %]"
+ maxlength="255" spellcheck="true" aria-required="true"
+ class="required text_input" id="short_desc">
+ </td>
+ </tr>
+
+ [% IF feature_enabled('jsonrpc') AND !cloned_bug_id %]
+ <tr id="possible_duplicates_container" class="bz_default_hidden">
+ <th>Possible<br>Duplicates:</th>
+ <td colspan="3">
+ <div id="possible_duplicates"></div>
+ <script type="text/javascript">
+ var dt_columns = [
+ { key: "id", label: "[% field_descs.bug_id FILTER js %]",
+ formatter: YAHOO.bugzilla.dupTable.formatBugLink },
+ { key: "summary",
+ label: "[% field_descs.short_desc FILTER js %]",
+ formatter: "text" },
+ { key: "status",
+ label: "[% field_descs.bug_status FILTER js %]",
+ formatter: YAHOO.bugzilla.dupTable.formatStatus },
+ { key: "update_token", label: '',
+ formatter: YAHOO.bugzilla.dupTable.formatCcButton }
+ ];
+ YAHOO.bugzilla.dupTable.addCcMessage = "Add Me to the CC List";
+ YAHOO.bugzilla.dupTable.init({
+ container: 'possible_duplicates',
+ columns: dt_columns,
+ product_name: '[% product.name FILTER js %]',
+ summary_field: 'short_desc',
+ options: {
+ MSG_LOADING: 'Searching for possible duplicates...',
+ MSG_EMPTY: 'No possible duplicates found.',
+ SUMMARY: 'Possible Duplicates'
+ }
+ });
+ </script>
+ </td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Description:</th>
+ <td colspan="3">
+
+ [% defaultcontent = BLOCK %]
+ [% IF cloned_bug_id %]
++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id FILTER html %] +++
+
+
+ [% END %]
+ [%-# We are within a BLOCK. The comment will be correctly HTML-escaped
+ # by global/textarea.html.tmpl. So we must not escape the comment here. %]
+ [% comment FILTER none %]
+ [%- END %]
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = defaultcontent
+ %]
+ <br>
+ </td>
+ </tr>
+
+<tbody class="expert_fields">
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.bug_file_loc editable = 1
+ %]
+ <td colspan="3" class="field_value">
+ <input name="bug_file_loc" id="bug_file_loc" class="text_input"
+ size="40" value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+</tbody>
+
+<tbody>
+ [% IF Param("maxattachmentsize") %]
+ <tr>
+ <th>Attachment:</th>
+ <td colspan="3">
+ <div id="attachment_false" class="bz_default_hidden">
+ <input type="button" value="Add an attachment" onClick="handleWantsAttachment(true)">
+ </div>
+
+ <div id="attachment_true">
+ <input type="button" id="btn_no_attachment" value="Don't add an attachment"
+ class="bz_default_hidden" onClick="handleWantsAttachment(false)">
+ <fieldset>
+ <legend>Add an attachment</legend>
+ <table class="attachment_entry">
+ [% PROCESS attachment/createformcontents.html.tmpl
+ flag_types = product.flag_types(is_active=>1).attachment
+ any_flags_requesteeble = 1
+ flag_table_id ="attachment_flags" %]
+ </table>
+
+ [% IF user.is_insider %]
+ <input type="checkbox" id="comment_is_private" name="comment_is_private"
+ [% ' checked="checked"' IF comment_is_private %]
+ onClick="updateCommentTagControl(this, 'comment')">
+ <label for="comment_is_private">
+ Make this attachment and [% terms.bug %] description private (visible only
+ to members of the <strong>[% Param('insidergroup') FILTER html %]</strong> group)
+ </label>
+ [% END %]
+ </fieldset>
+ </div>
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody class="expert_fields">
+ [% IF user.in_group('editbugs', product.id) %]
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.dependson editable = 1
+ %]
+ <td>
+ <input name="dependson" accesskey="d" value="[% dependson FILTER html %]" size="30">
+ </td>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.blocked editable = 1
+ %]
+ <td>
+ <input name="blocked" accesskey="b" value="[% blocked FILTER html %]" size="30">
+ </td>
+ </tr>
+
+ [% IF use_keywords %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.keywords, editable = 1,
+ value = keywords, desc_url = "describekeywords.cgi",
+ value_span = 3
+ %]
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Status Whiteboard:</th>
+ <td colspan="3" class="field_value">
+ <input id="status_whiteboard" name="status_whiteboard" size="70"
+ value="[% status_whiteboard FILTER html %]" class="text_input">
+ </td>
+ </tr>
+ [% END %]
+
+ [% IF user.is_timetracker %]
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.estimated_time editable = 1
+ %]
+ <td>
+ <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]">
+ </td>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.deadline, value = deadline, editable = 1
+ %]
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody>
+[%# non-tracking flags custom fields %]
+[% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT UNLESS field.enter_bug %]
+ [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 1) %]
+ [%# crash-signature gets custom handling %]
+ [% NEXT IF field.name == 'cf_crash_signature' %]
+
+ [% SET value = ${field.name}.defined ? ${field.name} : "" %]
+ <tr [% 'class="expert_fields"' IF !field.is_mandatory %]>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = field, value = value, editable = 1,
+ value_span = 3 %]
+ </tr>
+[% END %]
+</tbody>
+
+[%# crash-signature handling %]
+[% UNLESS cf_hidden_in_product('cf_crash_signature', product.name, component.name, 1) %]
+<tbody class="expert_fields">
+ <tr>
+ <th id="field_label_cf_crash_signature" class="field_label">
+ <label for="cf_crash_signature"> Crash Signature: </label>
+ </th>
+ <td colspan="3">
+ <span id="cf_crash_signature_container">
+ <span id="cf_crash_signature_nonedit_display"><i>None</i></span>
+ (<a id="cf_crash_signature_action" href="#">edit</a>)
+ </span>
+ <span id="cf_crash_signature_input">
+ <textarea id="cf_crash_signature" name="cf_crash_signature" rows="4" cols="60"
+ >[% cf_crash_signature FILTER html %]</textarea>
+ </span>
+ </td>
+ </tr>
+</tbody>
+[% END %]
+
+[% display_bug_flags = 0 %]
+[% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT UNLESS field.enter_bug %]
+ [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 2) %]
+ [% display_bug_flags = 1 %]
+ [% LAST %]
+[% END %]
+
+[% display_flags = 0 %]
+[% any_flags_requesteeble = 0 %]
+[% FOREACH flag_type = product.flag_types(is_active=>1).bug %]
+ [% display_flags = 1 %]
+ [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %]
+ [% LAST IF display_flags && any_flags_requesteeable %]
+[% END %]
+
+[% IF display_bug_flags || display_flags %]
+ <tbody class="expert_fields">
+ <tr>
+ <th>Flags:</th>
+ <td colspan="3">
+ <div id="bug_flags_false" class="bz_default_hidden">
+ <input type="button" value="Set [% terms.bug FILTER html %] flags" onClick="handleWantsBugFlags(true)">
+ </div>
+
+ <div id="bug_flags_true">
+ <input type="button" id="btn_no_bug_flags" value="Don't set [% terms.bug %] flags"
+ class="bz_default_hidden" onClick="handleWantsBugFlags(false)">
+
+ <fieldset>
+ <legend>Set [% terms.bug %] flags</legend>
+
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ [% IF display_bug_flags %]
+ <td>
+ <table id="bug_tracking_flags">
+ <tr>
+ <th colspan="2" style="text-align:left">Tracking Flags:</th>
+ </tr>
+ <tr>
+ [% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT UNLESS field.enter_bug %]
+ [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 2) %]
+
+ [% SET value = ${field.name}.defined ? ${field.name} : "" %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = field, value = value, editable = 1,
+ value_span = 3 %]
+ </tr>
+ [% END %]
+ </tr>
+ </table>
+ </td>
+ [% END %]
+ [% IF display_flags %]
+ <td>
+ [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types(is_active=>1).bug
+ any_flags_requesteeble = any_flags_requesteeble
+ flag_table_id = "bug_flags"
+ %]
+ </td>
+ [% END %]
+ </tr>
+ </table>
+ </fieldset>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+[% END %]
+
+<tbody>
+ [%# Form controls for entering additional data about the bug being created. %]
+ [% Hook.process("form") %]
+
+ <tr>
+ <th>&nbsp;</th>
+ <td colspan="3">
+ <input type="submit" id="commit" value="Submit [% terms.Bug %]">
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <input type="submit" name="maketemplate" id="maketemplate"
+ value="Remember values as bookmarkable template"
+ onclick="bz_no_validate_enter_bug=true" class="expert_fields">
+ </td>
+ </tr>
+</tbody>
+ [%# "status whiteboard" and "qa contact" are the longest labels
+ # add them here to avoid shifting the page when toggling advanced fields %]
+ <tr>
+ <th class="hidden_text">Status Whiteboard:</th>
+ <td>&nbsp;</td>
+ <th class="hidden_text">QA Contact:</th>
+ </tr>
+ </table>
+ <input type="hidden" name="form_name" value="enter_bug">
+</form>
+
+[%# Links or content with more information about the bug being created. %]
+[% Hook.process("end") %]
+
+<div id="guided">
+ <a id="guided_img" href="enter_bug.cgi?format=guided&amp;product=[% product.name FILTER uri %]"><img
+ src="extensions/BMO/web/images/guided.png" width="16" height="16" border="0" align="absmiddle"></a>
+ <a id="guided_link" href="enter_bug.cgi?format=guided&amp;product=[% product.name FILTER uri %]"
+ >Switch to the [% terms.Bugzilla %] Helper</a>
+</div>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[%############################################################################%]
+[%# Block for SELECT fields #%]
+[%############################################################################%]
+
+[% BLOCK select %]
+
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = field editable = 1
+ %]
+ <td>
+ <select name="[% field.name FILTER html %]"
+ id="[% field.name FILTER html %]">
+ [%- FOREACH x = ${field.name} %]
+ [% NEXT IF NOT x.is_active %]
+ <option value="[% x.name FILTER html %]"
+ [% " selected=\"selected\"" IF x.name == default.${field.name} %]>
+ [% display_value(field.name, x.name) FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+[% END %]
+
+[% BLOCK build_userlist %]
+ [% user_found = 0 %]
+ [% default_login = default_user.login %]
+ [% RETURN UNLESS default_login %]
+
+ [% FOREACH user = userlist %]
+ [% IF user.login == default_login %]
+ [% user_found = 1 %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+
+ [% userlist.push({login => default_login,
+ identity => default_user.identity,
+ visible => 1})
+ UNLESS user_found %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl
new file mode 100644
index 000000000..e9a480090
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl
@@ -0,0 +1,38 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Byron Jones <glob@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps - Application Form"
+
+%]
+
+<h1>Thank you!</h1>
+
+<p>
+Thank you for submitting your Mozilla Reps Application Form. A Mozilla Rep
+mentor will contact you shortly at your bugzilla email address.
+</p>
+
+<p style="font-size: x-small">
+Reference: <a href="show_bug.cgi?id=[% id FILTER uri %]">#[% id FILTER html %]</a>
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
new file mode 100644
index 000000000..8e33caec5
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
@@ -0,0 +1,54 @@
+<!-- 1.0@bugzilla.org -->
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Matthew Tuck <matty@chariot.net.au>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+<p>
+ [% UNLESS cloned_bug_id %]
+ Consider using the
+ <a href="enter_bug.cgi?product=[% product.name FILTER html %]&amp;format=guided"
+ ><img src="extensions/BMO/web/images/guided.png" width="16" height="16" align="absmiddle" border="0">
+ [%+ terms.Bugzilla %] Helper</a> instead of this form.
+ [% END +%]
+ Before reporting a [% terms.bug %], make sure you've read our
+ <a href="http://www.mozilla.org/quality/bug-writing-guidelines.html">
+ [% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already
+ been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi">
+ most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi">
+ search through descriptions</a> of previously reported [% terms.bugs %].
+</p>
+
+[% IF product.name == 'Bugzilla' &&
+ (user.in_group('mozilla-corporation') || user.in_group('mozilla-foundation')) %]
+ <div id="bug_create_warning">
+ <div id="bug_create_warning_image">
+ <img src="extensions/BMO/web/images/sign_warning.png" width="32" height="32">
+ </div>
+ <div id="bug_create_warning_text">
+ <b>Mozilla employees</b><br>
+ This is not the place to request configuration, permission, or
+ account changes to this installation of [% terms.Bugzilla %] (bugzilla.mozilla.org).<br>
+ File such changes under the appropriate component in the
+ <a href="enter_bug.cgi?product=bugzilla.mozilla.org;component=Administration"><b>bugzilla.mozilla.org</b></a>
+ product.
+ </div>
+ </div>
+[% END %]
diff --git a/extensions/BMO/template/en/default/email/bugmail.html.tmpl b/extensions/BMO/template/en/default/email/bugmail.html.tmpl
new file mode 100644
index 000000000..e40c8239a
--- /dev/null
+++ b/extensions/BMO/template/en/default/email/bugmail.html.tmpl
@@ -0,0 +1,223 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS "global/reason-descs.none.tmpl" %]
+
+[% isnew = bug.lastdiffed ? 0 : 1 %]
+<html>
+<head>
+ <base href="[% urlbase FILTER html %]">
+ <style>
+ body {
+ font-family: sans-serif;
+ color: #444444;
+ }
+ hr {
+ border: 1px dashed #969696;
+ }
+ .diffs .head td {
+ border-bottom: 1px solid #969696;
+ }
+ .diffs .c1, .diffs .c2 {
+ border-right: 1px solid #969696;
+ }
+ .new .c1 {
+ border-right: 1px solid #969696;
+ }
+ #noreply, #reason, #tracking, #bug_details {
+ font-size: 90%;
+ color: #666666;
+ }
+ </style>
+</head>
+<body>
+
+ [% IF !to_user.in_group('editbugs') %]
+ <div id="noreply">
+ Do not reply to this email. You can add comments to this [% terms.bug %] at
+ [%# using the bug_link filter here causes a weird template error %]
+ <a href="[% urlbase FILTER html %]show_bug.cgi?id=[% bug.id FILTER none %]">
+ [% urlbase FILTER html %]show_bug.cgi?id=[% bug.id FILTER none %]</a>
+ </div>
+ <br>
+ [% END %]
+
+ [% IF isnew %]
+ [% PROCESS generate_new %]
+ [% ELSE %]
+ [% PROCESS generate_diffs %]
+ [% END %]
+
+ [% IF new_comments.size %]
+ <div id="comments">
+ [% FOREACH comment = new_comments.reverse %]
+ <div>
+ [% IF comment.count %]
+ <b>
+ [% "Comment # ${comment.count}"
+ FILTER bug_link(bug, { comment_num => comment.count, full_url => 1 }) FILTER none %]
+ on [% "$terms.Bug $bug.id" FILTER bug_link(bug, { full_url => 1 }) FILTER none %]
+ from [% INCLUDE global/user.html.tmpl who = comment.author %]
+ at [% comment.creation_ts FILTER time(undef, to_user.timezone) %]
+ </b>
+ [% END %]
+ <pre>[% comment.body_full({ wrap => 1 }) FILTER quoteUrls(bug, comment) %]</pre>
+ </div>
+ [% END %]
+ </div>
+ <br>
+ [% END %]
+
+ [% IF referenced_bugs.size %]
+ <div id="referenced">
+ <hr>
+ <b>Referenced [% terms.Bugs %]:</b>
+ <ul>
+ [% FOREACH ref = referenced_bugs %]
+ <li>
+ [<a href="[% urlbase FILTER html %]show_bug.cgi?id=[% ref.id FILTER none %]">
+ [% terms.Bug %]&nbsp;[% ref.id FILTER none %]</a>] [% ref.short_desc FILTER html %]
+ </li>
+ [% END %]
+ </ul>
+ </div>
+ <br>
+ [% END %]
+
+ <div id="bug_details">
+ <hr>
+ Product/Component: [% bug.product FILTER html %] :: [% bug.component FILTER html %]
+ </div>
+
+[% USE Bugzilla %]
+[% tracking_flags = [] %]
+[% FOREACH field = Bugzilla.active_custom_fields(product => bug.product_obj, component => bug.component_obj, type => 2) %]
+ [% NEXT IF cf_flag_disabled(field.name, bug) %]
+ [% NEXT IF bug.${field.name} == "---" %]
+ [% tracking_flags.push(field) %]
+[% END %]
+[% IF tracking_flags.size %]
+ <div id="tracking">
+ <hr>
+ <b>Tracking Flags:</b>
+ <ul>
+ [% FOREACH field = tracking_flags %]
+ <li>[% field.description FILTER html %]:[% bug.${field.name} FILTER html %]</li>
+ [% END %]
+ </ul>
+ </div>
+[% END %]
+
+ <div id="reason">
+ <hr>
+ <b>You are receiving this mail because:</b>
+ <ul>
+ [% FOREACH reason = reasons %]
+ [% IF reason_descs.$reason %]
+ <li>[% reason_descs.$reason FILTER html %]</li>
+ [% END %]
+ [% END %]
+ [% FOREACH reason = reasons_watch %]
+ [% IF watch_reason_descs.$reason %]
+ <li>[% watch_reason_descs.$reason FILTER html %]</li>
+ [% END %]
+ [% END %]
+ </ul>
+ </div>
+
+</body>
+</html>
+
+[% BLOCK generate_new %]
+ <div class="new">
+ <table border="0" cellspacing="0" cellpadding="3">
+ [% FOREACH change = diffs %]
+ [% PROCESS "email/bugmail-common.txt.tmpl" %]
+ <tr>
+ <td class="c1" nowrap><b>[% field_label FILTER html %]</b></td>
+ <td class="c2">
+ [% IF change.field_name == "bug_id" %]
+ [% new_value FILTER bug_link(bug, full_url => 1) FILTER none %]
+ [% ELSE %]
+ [% new_value FILTER html %]
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </div>
+ <br>
+[% END %]
+
+[% BLOCK generate_diffs %]
+ [% SET in_table = 0 %]
+ [% last_changer = 0 %]
+ [% FOREACH change = diffs %]
+ [% PROCESS "email/bugmail-common.txt.tmpl" %]
+ [% IF changer.id != last_changer %]
+ [% last_changer = changer.id %]
+ [% IF in_table == 1 %]
+ </table>
+ </div>
+ <br>
+ [% SET in_table = 0 %]
+ [% END %]
+
+ <b>
+ [% IF change.blocker %]
+ [% "${terms.Bug} ${bug.id}" FILTER bug_link(bug, full_url => 1) FILTER none %]
+ depends on
+ <a href="[% urlbase FILTER html %]show_bug.cgi?id=[% change.blocker.id FILTER none %]">
+ [% terms.Bug %]&nbsp;[% change.blocker.id FILTER none %]</a>,
+ which changed state.<br>
+ [% ELSE %]
+ [% INCLUDE global/user.html.tmpl who = change.who %] changed
+ [%+ "${terms.Bug} ${bug.id}" FILTER bug_link(bug, full_url => 1) FILTER none %]
+ at [% change.bug_when FILTER time(undef, to_user.timezone) %]</b>:<br>
+ [% END %]
+ </b>
+
+ [% IF in_table == 0 %]
+ <br>
+ <div class="diffs">
+ <table border="0" cellspacing="0" cellpadding="5">
+ [% SET in_table = 1 %]
+ [% END %]
+ <tr class="head">
+ <td class="c1"><b>What</b></td>
+ <td class="c2"><b>Removed</b></td>
+ <td class="c3"><b>Added</b></td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <td class="c1" nowrap>[% field_label FILTER html %]</td>
+ <td class="c2">
+ [% IF old_value %]
+ [% old_value FILTER html %]
+ [% ELSE %]
+ &nbsp;
+ [% END %]
+ </td>
+ <td>
+ [% IF new_value %]
+ [% new_value FILTER html %]
+ [% ELSE %]
+ &nbsp;
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ [% IF in_table %]
+ </table>
+ </div>
+ <br>
+ [% END %]
+[% END %]
+
diff --git a/extensions/BMO/template/en/default/email/bugmail.txt.tmpl b/extensions/BMO/template/en/default/email/bugmail.txt.tmpl
new file mode 100644
index 000000000..76fa492ee
--- /dev/null
+++ b/extensions/BMO/template/en/default/email/bugmail.txt.tmpl
@@ -0,0 +1,93 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS "global/reason-descs.none.tmpl" %]
+
+[% isnew = bug.lastdiffed ? 0 : 1 %]
+
+[% IF !to_user.in_group('editbugs') %]
+Do not reply to this email. You can add comments to this [% terms.bug %] at
+[% END %]
+[%+ PROCESS generate_diffs -%]
+
+[% FOREACH comment = new_comments %]
+
+[%- IF comment.count %]
+--- Comment #[% comment.count %] from [% comment.author.identity %] [%+ comment.creation_ts FILTER time(undef, to_user.timezone) %] ---
+[% END %]
+[%+ comment.body_full({ is_bugmail => 1, wrap => 1 }) %]
+[% END %]
+[% IF referenced_bugs.size %]
+
+Referenced [% terms.Bugs %]:
+
+[% FOREACH ref = referenced_bugs %]
+[%+ urlbase %]show_bug.cgi?id=[% ref.id %]
+[%+ "[" _ terms.Bug _ " " _ ref.id _ "] " _ ref.short_desc FILTER wrap_comment(76) %]
+[% END %]
+[% END %]
+
+-- [%# Protect the trailing space of the signature marker %]
+Configure [% terms.bug %]mail: [% urlbase %]userprefs.cgi?tab=email
+
+-------------------------------
+Product/Component: [%+ bug.product +%] :: [%+ bug.component %]
+
+[% USE Bugzilla %]
+[% tracking_flags = [] %]
+[% FOREACH field = Bugzilla.active_custom_fields(product => bug.product_obj, component => bug.component_obj, type => 2) %]
+ [% NEXT IF cf_flag_disabled(field.name, bug) %]
+ [% NEXT IF bug.${field.name} == "---" %]
+ [% tracking_flags.push(field) %]
+[% END %]
+[% IF tracking_flags.size %]
+------- Tracking Flags: -------
+[% FOREACH field = tracking_flags %]
+[%+ field.description %]:[% bug.${field.name} %]
+[% END %]
+[% END %]
+
+------- You are receiving this mail because: -------
+[% SET reason_lines = [] %]
+[% FOREACH reason = reasons %]
+ [% reason_lines.push(reason_descs.$reason) IF reason_descs.$reason %]
+[% END %]
+[% FOREACH reason = reasons_watch %]
+ [% reason_lines.push(watch_reason_descs.$reason)
+ IF watch_reason_descs.$reason %]
+[% END %]
+[%+ reason_lines.join("\n") %]
+
+[% BLOCK generate_diffs %]
+ [% urlbase %]show_bug.cgi?id=[% bug.id %]
+
+[%+ last_changer = 0 %]
+ [% FOREACH change = diffs %]
+ [% IF !isnew && changer.id != last_changer %]
+ [% last_changer = changer.id %]
+ [% IF change.blocker %]
+ [% terms.Bug %] [%+ bug.id %] depends on [% terms.bug %] [%+ change.blocker.id %], which changed state.
+
+[%+ terms.Bug %] [%+ change.blocker.id %] Summary: [% change.blocker.short_desc %]
+[%+ urlbase %]show_bug.cgi?id=[% change.blocker.id %]
+ [% ELSE %]
+ [%~ changer.identity %] changed:
+ [% END %]
+
+ What |Removed |Added
+----------------------------------------------------------------------------
+[%+ END %][%# End of IF. This indentation is intentional! ~%]
+ [% PROCESS "email/bugmail-common.txt.tmpl"%]
+ [%~ IF isnew %]
+ [% format_columns(2, field_label _ ":", new_value) -%]
+ [% ELSE %]
+ [% format_columns(3, field_label, old_value, new_value) -%]
+ [% END %]
+ [% END -%]
+[% END %]
diff --git a/extensions/BMO/template/en/default/global/choose-product.html.tmpl b/extensions/BMO/template/en/default/global/choose-product.html.tmpl
new file mode 100644
index 000000000..38a43cd12
--- /dev/null
+++ b/extensions/BMO/template/en/default/global/choose-product.html.tmpl
@@ -0,0 +1,228 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ #%]
+
+[%# INTERFACE:
+ # classifications: array of hashes, with an 'object' key representing a
+ # classification object and 'products' the list of
+ # product objects the user can enter bugs into.
+ # target: the script that displays this template.
+ # cloned_bug_id: ID of the bug being cloned.
+ # format: the desired format to display the target.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% style_urls = [ "extensions/BMO/web/styles/choose_product.css" ] %]
+
+[% IF target == "enter_bug.cgi" %]
+ [% title = "Enter $terms.Bug" %]
+ [% h2 = "Which product is affected by the problem you would like to report?" %]
+[% ELSIF target == "describecomponents.cgi" %]
+ [% title = "Browse" %]
+ [% h2 = "Which product would you like to have described?" %]
+[% END %]
+
+[% javascript_urls = [ "js/yui3/yui/yui-min.js",
+ "extensions/ProdCompSearch/web/js/prod_comp_search.js" ]
+%]
+[% onload = "document.getElementById('prod_comp_search').focus();" %]
+[% style_urls.push("extensions/ProdCompSearch/web/styles/prod_comp_search.css") %]
+
+[% DEFAULT title = "Choose a Product" %]
+[% PROCESS global/header.html.tmpl %]
+
+<div id="choose_product">
+
+<hr>
+<p>
+ Looking for technical support or help getting your site to work with Mozilla?
+ <a href="http://www.mozilla.org/support/">Visit the mozilla.org support page</a>
+ before filing [% terms.bugs %].
+</p>
+<hr>
+
+<h2>[% h2 FILTER html %]</h2>
+
+<div id="prod_comp_search_main">
+ [% PROCESS prodcompsearch/form.html.tmpl
+ input_label = "Find product:"
+ format = format
+ cloned_bug_id = cloned_bug_id
+ script_name = target %]
+</div>
+
+<h2>or choose from the following selections</h2>
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+[% SET classification = cgi.param('classification') %]
+[% IF NOT ((cgi.param("full")) OR (user.settings.product_chooser.value == 'full_product_chooser')) %]
+
+<table align="center" border="0" width="600" cellpadding="5" cellspacing="0">
+[% INCLUDE easyproduct
+ name="Core"
+ icon="dino.png"
+%]
+[% INCLUDE easyproduct
+ name="Firefox"
+ icon="firefox.png"
+%]
+[% INCLUDE easyproduct
+ name="Boot2Gecko"
+ icon="firefox.png"
+ caption="Firefox OS"
+%]
+[% INCLUDE easyproduct
+ name="Firefox for Android"
+ icon="firefox.png"
+%]
+[% INCLUDE easyproduct
+ name="Firefox for Metro"
+ icon="firefox.png"
+%]
+[% INCLUDE easyproduct
+ name="Toolkit"
+ icon="dino.png"
+%]
+[% INCLUDE easyproduct
+ name="Marketplace"
+ icon="marketplace.png"
+%]
+[% INCLUDE easyproduct
+ name="Thunderbird"
+ icon="thunderbird.png"
+%]
+[% INCLUDE easyproduct
+ name="SeaMonkey"
+ icon="seamonkey.png"
+%]
+[% INCLUDE easyproduct
+ name="Mozilla Localizations"
+ icon="dino.png"
+%]
+[% INCLUDE easyproduct
+ name="Mozilla Services"
+ icon="dino.png"
+%]
+<tr>
+ <td><a href="[% target FILTER uri %]?full=1
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF classification %]&amp;classification=[% classification FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ <img src="extensions/BMO/web/producticons/other.png" height="64" width="64" border="0"></a></td>
+ <td><h2 align="left" style="margin-bottom: 0px;"><a href="[% target FILTER uri %]?full=1
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF classification %]&amp;classification=[% classification FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ Other Products</a></h2>
+ <p style="margin-top: 0px;">Other Mozilla products which aren't listed here</p>
+ </td>
+</tr>
+</table>
+[% ELSE %]
+
+<table>
+
+[% FOREACH c = classifications %]
+ [% IF c.object %]
+ <tr>
+ <td align="right"><h2>[% c.object.name FILTER html %]</h2></td>
+ <td><strong>[%+ c.object.description FILTER html_light %]</strong></td>
+ </tr>
+ [% END %]
+
+ [% FOREACH p = c.products %]
+ [% class = "" %]
+ [% has_entry_groups = 0 %]
+ [% FOREACH gid = p.group_controls.keys %]
+ [% IF p.group_controls.$gid.entry %]
+ [% has_entry_groups = 1 %]
+ [% class = class _ " group_$gid" %]
+ [% END %]
+ [% END %]
+ <tr class="[% "group_secure" IF has_entry_groups +%] [% class FILTER html %]"
+ [%- IF has_entry_groups %] title="This product requires one or more
+ group memberships in order to enter [% terms.bugs %] in it. You have them, but be
+ aware not everyone else does."[% END %]>
+ <th align="right" valign="top">
+ [% IF p.name == "Mozilla PR" AND target == "enter_bug.cgi" AND NOT format AND NOT cgi.param("debug") %]
+ <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END %]&amp;format=mozpr">
+ [% p.name FILTER html FILTER no_break %]</a>:&nbsp;
+ [% ELSE %]
+ <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ [% p.name FILTER html FILTER no_break %]</a>:&nbsp;
+ [% END %]
+ </th>
+ <td valign="top">[% p.description FILTER html_light %]</td>
+ </tr>
+ [% END %]
+[% END %]
+
+</table>
+
+<br>
+[% IF target == "enter_bug.cgi" AND user.settings.product_chooser.value != 'full_product_chooser' %]
+<p>You can choose to get this screen by default when you click "New [% terms.Bug %]"
+by changing your <a href="userprefs.cgi?tab=settings">preferences</a>.</p>
+[% END %]
+[% END %]
+<br>
+
+</div>
+
+<div id="guided">
+ <a id="guided_img" href="enter_bug.cgi?format=guided"><img
+ src="extensions/BMO/web/images/guided.png" width="16" height="16" border="0" align="absmiddle"></a>
+ <a id="guided_link" href="enter_bug.cgi?format=guided"
+ >Switch to the [% terms.Bugzilla %] Helper</a>
+</div>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[%###########################################################################%]
+[%# Block for "easy" product sections #%]
+[%###########################################################################%]
+
+[% BLOCK easyproduct %]
+ [% FOREACH c = classifications %]
+ [% FOREACH p = c.products %]
+ [% IF p.name == name %]
+ <tr>
+ <td><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ <img src="extensions/BMO/web/producticons/[% icon FILTER uri %]" height="64" width="64" border="0"></a></td>
+ <td><h2 align="left" style="margin-bottom: 0px"><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ [% caption || name FILTER html FILTER no_break %]</a>:</h2>
+ [% IF p.description %]
+ <p style="margin-top: 0px;">[% p.description FILTER html_light %]</p>
+ [% END %]
+ </td>
+ </tr>
+ [% LAST %]
+ [% END %]
+ [% END %]
+ [% END %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/global/common-links.html.tmpl b/extensions/BMO/template/en/default/global/common-links.html.tmpl
new file mode 100644
index 000000000..4fbbb25a0
--- /dev/null
+++ b/extensions/BMO/template/en/default/global/common-links.html.tmpl
@@ -0,0 +1,124 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Svetlana Harisova <light@rathedg.com>
+ #%]
+
+[% DEFAULT qs_suffix = "" %]
+[% USE Bugzilla %]
+
+<ul class="links">
+ <li><a href="./">Home</a></li>
+ <li><span class="separator">| </span><a href="enter_bug.cgi">New</a></li>
+ <li><span class="separator">| </span><a href="describecomponents.cgi">Browse</a></li>
+ <li><span class="separator">| </span><a href="query.cgi">Search</a></li>
+
+ <li class="form">
+ <span class="separator">| </span>
+ <form action="buglist.cgi" method="get"
+ onsubmit="if (this.quicksearch.value == '')
+ { alert('Please enter one or more search terms first.');
+ return false; } return true;">
+ <input class="txt" type="text" id="quicksearch[% qs_suffix FILTER html %]" name="quicksearch"
+ title="Quick Search" value="[% quicksearch FILTER html %]">
+ <input class="btn" type="submit" value="Search"
+ id="find[% qs_suffix FILTER html %]">
+ [%-# Work around FF bug: keep this on one line %]</form>
+ [<a href="page.cgi?id=quicksearch.html" title="Quicksearch Help">help</a>]
+ </li>
+
+ <li><span class="separator">| </span><a href="report.cgi">Reports</a></li>
+
+ [% IF user.settings.skin.value != 'Mozilla' %]
+ <li>
+ [% IF Param('shutdownhtml') || Bugzilla.has_flags %]
+ <span class="separator">| </span>
+ [% IF user.id %]
+ <a href="request.cgi?requester=[% user.login FILTER uri %]&amp;requestee=
+ [% user.login FILTER uri %]&amp;do_union=1&amp;group=type&amp;action=queue">My Requests</a>
+ [% ELSE %]
+ <a href="request.cgi">Requests</a>
+ [% END %]
+ [% END %]
+ [%-# Work around FF bug: keep this on one line %]</li>
+ [% END %]
+
+ [% Hook.process('action-links') %]
+
+ [% IF user.settings.skin.value != 'Mozilla' %]
+ [% IF user.login %]
+ <li><span class="separator">| </span><a href="userprefs.cgi">Preferences</a></li>
+ [% IF user.in_group('tweakparams') || user.in_group('editusers') || user.can_bless
+ || (Param('useclassification') && user.in_group('editclassifications'))
+ || user.in_group('editcomponents') || user.in_group('admin') || user.in_group('creategroups')
+ || user.in_group('editkeywords') || user.in_group('bz_canusewhines')
+ || user.get_products_by_permission("editcomponents").size %]
+ <li><span class="separator">| </span><a href="admin.cgi">Administration</a></li>
+ [% END %]
+
+ [% PROCESS link_to_documentation %]
+
+ <li>
+ <span class="separator">| </span>
+ [% IF user.authorizer.can_logout %]
+ <a href="index.cgi?logout=1">Log&nbsp;out</a>
+ [% ELSE %]
+ Logged&nbsp;in&nbsp;as
+ [% END %]
+ [% IF sudoer %]
+ [%+ sudoer.login FILTER html %] (<b>impersonating
+ [%+ user.login FILTER html %]</b>
+ <a href="relogin.cgi?action=end-sudo">end session</a>)
+ [% ELSE %]
+ [%+ user.login FILTER html %]
+ [% END %]
+ [%-# Work around FF bug: keep this on one line %]</li>
+ [% ELSE %]
+
+ [% PROCESS link_to_documentation %]
+
+ [% IF Param('createemailregexp')
+ && user.authorizer.user_can_create_account %]
+ <li id="new_account_container[% qs_suffix FILTER html %]">
+ <span class="separator">| </span>
+ <a href="createaccount.cgi">New&nbsp;Account</a>
+ </li>
+ [% END %]
+
+ [%# Only display one login form when we're on a LOGIN_REQUIRED page. That
+ # way, we're guaranteed that the user will use the form that has
+ # hidden_fields in it (the center form) instead of this one. Also, it's
+ # less confusing to have one form (as opposed to three) when you're
+ # required to log in.
+ #%]
+ [% IF user.authorizer.can_login && !Bugzilla.page_requires_login %]
+ [% PROCESS "account/auth/login-small.html.tmpl" %]
+ [% END %]
+ [% END %]
+ [% END %]
+</ul>
+
+[% Hook.process("link-row") %]
+[% BLOCK link_to_documentation %]
+ [% IF doc_section && Param('docs_urlbase') %]
+ <li>
+ <span class="separator">| </span>
+ <a href="[% docs_urlbase _ doc_section FILTER html %]" target="_blank">Help</a>
+ </li>
+ [% END %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/global/header.html.tmpl b/extensions/BMO/template/en/default/global/header.html.tmpl
new file mode 100644
index 000000000..6aaac9411
--- /dev/null
+++ b/extensions/BMO/template/en/default/global/header.html.tmpl
@@ -0,0 +1,416 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Vaskin Kissoyan <vkissoyan@yahoo.com>
+ # Vitaly Harisov <vitaly@rathedg.com>
+ # Svetlana Harisova <light@rathedg.com>
+ #%]
+
+[%# INTERFACE:
+ # (All the below interface elements are optional.)
+ # title: string. Page title.
+ # header: string. Main page header.
+ # subheader: string. Page subheader.
+ # header_addl_info: string. Additional header information.
+ # bodyclasses: array of extra CSS classes for the <body>
+ # onload: string. JavaScript code to run when the page finishes loading.
+ # javascript: string. Javascript to go in the header.
+ # javascript_urls: list. List of URLs to Javascript.
+ # style: string. CSS style.
+ # style_urls: list. List of URLs to CSS style sheets.
+ # message: string. A message to display to the user. May contain HTML.
+ # atomlink: Atom link URL, May contain HTML
+ #%]
+
+[% IF message %]
+ [% PROCESS global/messages.html.tmpl %]
+[% END %]
+
+[% DEFAULT
+ subheader = ""
+ header_addl_info = ""
+ onload = ""
+ style_urls = []
+ yui = []
+%]
+
+[% SET yui_css = {
+ autocomplete => 1,
+ calendar => 1,
+ datatable => 1,
+ button => 1,
+} %]
+
+[%# Note: This is simple dependency resolution--you can't have dependencies
+ # that depend on each other. You have to specify all of a module's deps,
+ # if that module is going to be specified in "yui".
+ #%]
+[% SET yui_deps = {
+ autocomplete => ['json', 'connection', 'datasource'],
+ datatable => ['json', 'connection', 'datasource', 'element'],
+} %]
+
+[%# When using certain YUI modules, we need to process certain
+ # extra JS templates.
+ #%]
+[% SET yui_templates = {
+ datatable => ['global/value-descs.js.tmpl'],
+} %]
+
+[%# These are JS URLs that are *always* on the page and come before
+ # every other JS URL.
+ #%]
+[% SET starting_js_urls = [
+ "js/yui/yahoo-dom-event/yahoo-dom-event.js",
+ "js/yui/cookie/cookie-min.js",
+] %]
+
+
+[%# We should be able to set the default value of the header variable
+ # to the value of the title variable using the DEFAULT directive,
+ # but that doesn't work if a caller sets header to the empty string
+ # to avoid header inheriting the value of title, since DEFAULT
+ # mistakenly treats empty strings as undefined and gives header the
+ # value of title anyway. To get around that problem we explicitly
+ # set header's default value here only if it is undefined. %]
+[% IF !header.defined %][% header = title %][% END %]
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+ <head>
+ [% Hook.process("start") %]
+ <title>[% title FILTER none %]</title>
+
+ [% IF Param('utf8') %]
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ [% END %]
+
+[%# Migration note: contents of the old Param 'headerhtml' would go here %]
+
+ [% PROCESS "global/site-navigation.html.tmpl" %]
+
+ [% PROCESS 'global/setting-descs.none.tmpl' %]
+
+ [% SET yui = yui_resolve_deps(yui, yui_deps) %]
+ [% SET css_sets = css_files(style_urls, yui, yui_css) %]
+
+ [%# CSS cascade, parts 1 & 2: YUI & Standard Bugzilla stylesheet set (persistent).
+ # Always present. %]
+ <link href="[% 'skins/standard/global.css' FILTER mtime FILTER html %]"
+ rel="alternate stylesheet"
+ title="[% setting_descs.standard FILTER html %]">
+ [% FOREACH style_url = css_sets.standard %]
+ [% PROCESS format_css_link css_set_name = 'standard' %]
+ [% END %]
+
+ [%# CSS cascade, part 3: Third-party stylesheet set, per user prefs. %]
+ [% FOREACH style_url = css_sets.skin %]
+ [% PROCESS format_css_link css_set_name = user.settings.skin.value %]
+ [% END %]
+
+ [%# CSS cascade, part 4: page-specific styles. %]
+ [% IF style %]
+ <style type="text/css">
+ [% style FILTER none %]
+ </style>
+ [% END %]
+
+ [%# CSS cascade, part 5: Custom Bugzilla stylesheet set (persistent).
+ # Always present. Site administrators may override all other style
+ # definitions, including skins, using custom stylesheets.
+ #%]
+ [% FOREACH style_url = css_sets.custom %]
+ [% PROCESS format_css_link css_set_name = 'standard' %]
+ [% END %]
+
+ [%# YUI Scripts %]
+ [% FOREACH yui_name = yui %]
+ [% starting_js_urls.push("js/yui/$yui_name/${yui_name}-min.js") %]
+ [% END %]
+ [% starting_js_urls.push('js/global.js') %]
+
+ [% FOREACH javascript_url = starting_js_urls %]
+ [% PROCESS format_js_link %]
+ [% END %]
+
+ <script type="text/javascript">
+ <!--
+ YAHOO.namespace('bugzilla');
+ YAHOO.util.Event.addListener = function (el, sType, fn, obj, overrideContext) {
+ if ( ("onpagehide" in window || YAHOO.env.ua.gecko) && sType === "unload") { sType = "pagehide"; };
+ var capture = ((sType == "focusin" || sType == "focusout") && !YAHOO.env.ua.ie) ? true : false;
+ return this._addListener(el, this._getType(sType), fn, obj, overrideContext, capture);
+ };
+ if ( "onpagehide" in window || YAHOO.env.ua.gecko) {
+ YAHOO.util.Event._simpleRemove(window, "unload",
+ YAHOO.util.Event._unload);
+ }
+ [%# The language selector needs javascript to set its cookie,
+ # so it is hidden in HTML/CSS by the "bz_default_hidden" class.
+ # If the browser can run javascript, it will then "unhide"
+ # the language selector using the following code.
+ #%]
+ function unhide_language_selector() {
+ YAHOO.util.Dom.removeClass(
+ 'lang_links_container', 'bz_default_hidden'
+ );
+ }
+ YAHOO.util.Event.onDOMReady(unhide_language_selector);
+
+ [%# Make some Bugzilla information available to all scripts.
+ # We don't import every parameter and constant because we
+ # don't want to add a lot of uncached JS to every page.
+ #%]
+ var BUGZILLA = {
+ param: {
+ cookiepath: '[% Param('cookiepath') FILTER js %]',
+ maxusermatches: [% Param('maxusermatches') FILTER js %]
+ },
+ constant: {
+ COMMENT_COLS: [% constants.COMMENT_COLS FILTER js %]
+ },
+ string: {
+ [%# Please keep these in alphabetical order. %]
+
+ attach_desc_required:
+ 'You must enter a Description for this attachment.',
+ component_required:
+ 'You must select a Component for this [% terms.bug %].',
+ description_required:
+ 'You must enter a Description for this [% terms.bug %].',
+ short_desc_required:
+ 'You must enter a Summary for this [% terms.bug %].',
+ version_required:
+ 'You must select a Version for this [% terms.bug %].'
+ }
+ };
+
+ [% FOREACH yui_name = yui %]
+ [% FOREACH yui_template = yui_templates.$yui_name %]
+ [% INCLUDE $yui_template %]
+ [% END %]
+ [% END %]
+ [% IF javascript %]
+ [% javascript FILTER none %]
+ [% END %]
+ // -->
+ </script>
+
+ [% FOREACH javascript_url = javascript_urls %]
+ [% PROCESS format_js_link %]
+ [% END %]
+
+ [%# this puts the live bookmark up on firefox for the Atom feed %]
+ [% IF atomlink %]
+ <link rel="alternate"
+ type="application/atom+xml" title="Atom feed"
+ href="[% atomlink FILTER html %]">
+ [% END %]
+
+ [%# Required for the 'Autodiscovery' feature in Firefox 2 and IE 7. %]
+ <link rel="search" type="application/opensearchdescription+xml"
+ title="[% terms.BugzillaTitle %]" href="./search_plugin.cgi">
+ [% Hook.process("additional_header") %]
+ </head>
+
+[%# Migration note: contents of the old Param 'bodyhtml' go in the body tag,
+ # but set the onload attribute in the DEFAULT directive above.
+ #%]
+
+ <body onload="[% onload FILTER none %]"
+ class="[% urlbase.replace('^https?://','').replace('/$','').replace('[-~@:/.]+','-') %]
+ [% FOREACH class = bodyclasses %]
+ [% ' ' %][% class FILTER css_class_quote %]
+ [% END %] yui-skin-sam">
+
+[%# Migration note: the following file corresponds to the old Param
+ # 'bannerhtml'
+ #%]
+
+<div id="header">
+
+[% IF user.settings.skin.value == 'Mozilla' %]
+
+ <div class="wrapper">
+ <table border="0" cellspacing="0" cellpadding="0" id="titles">
+ <tr>
+ <td id="title">
+ <a href="./" title="Home">[% terms.BugzillaTitle %]</a>
+ </td>
+ <td id="information"></td>
+ <td id="languages">
+ [% IF Bugzilla.languages.size > 1 %]
+ <ul class="links">
+ [% FOREACH lang = Bugzilla.languages.sort %]
+ <li>[% IF NOT loop.first %]<span class="separator"> | </span>[% END %]
+ [% IF lang == current_language %]
+ <span class="lang_current">[% lang FILTER html FILTER upper %]</span>
+ [% ELSE %]
+ <a href="#" onclick="set_language('[% lang FILTER none %]');">
+ [%- lang FILTER html FILTER upper %]</a>
+ [% END %]
+ </li>
+ [% END %]
+ </ul>
+ [% END %]
+ </td>
+ <td id="login">
+ [% IF user.id %]
+ <ul class="links">
+ <li class="dropdown">
+ <span class="anchor">[% user.login FILTER html %]</span>
+ <ul>
+ [% IF user.showmybugslink %]
+ [% filtered_username = user.login FILTER uri %]
+ <li><a href="[% Param('mybugstemplate').replace('%userid%', filtered_username) %]">My [% terms.Bugs %]</a></li>
+ [% END %]
+ <li><a href="userprefs.cgi">Preferences</a></li>
+ <li><a href="request.cgi?requester=[% user.login FILTER uri %]&amp;requestee=[% user.login FILTER uri %]&amp;do_union=1&amp;group=type&amp;action=queue">My Requests</a></li>
+ [% IF user.in_group('tweakparams') || user.in_group('editusers') || user.can_bless
+ || (Param('useclassification') && user.in_group('editclassifications'))
+ || user.in_group('editcomponents') || user.in_group('admin') || user.in_group('creategroups')
+ || user.in_group('editkeywords') || user.in_group('bz_canusewhines')
+ || user.get_products_by_permission("editcomponents").size %]
+ <li><a href="admin.cgi">Administration</a></li>
+ [% END %]
+ [% IF user.authorizer.can_logout %]
+ <li><a href="index.cgi?logout=1">Log&nbsp;out</a></li>
+ [% END %]
+ [% IF sudoer %]
+ <li>
+ <a href="relogin.cgi?action=end-sudo">End sudo session impersonating [% user.login FILTER html %]</a>
+ </li>
+ [% END %]
+ </ul>
+ </li>
+ </ul>
+ [% ELSE %]
+ <ul class="login-links">
+ [% IF Param('createemailregexp')
+ && user.authorizer.user_can_create_account %]
+ <li id="new_account_container_top"><a href="createaccount.cgi">New&nbsp;Account</a></li>
+ [% END %]
+
+ [%# Only display one login form when we're on a LOGIN_REQUIRED page. That
+ # way, we're guaranteed that the user will use the form that has
+ # hidden_fields in it (the center form) instead of this one. Also, it's
+ # less confusing to have one form (as opposed to three) when you're
+ # required to log in.
+ #%]
+ [% IF user.authorizer.can_login && !Bugzilla.page_requires_login %]
+ [% PROCESS "account/auth/login-small.html.tmpl" %]
+ [% END %]
+ </ul>
+ [% END %]
+ </td>
+ <td id="tab">
+ <a href="http://mozilla.org/"><img src="https://addons.cdn.mozilla.net/media/img/zamboni/mozilla-tab.png?b=4953ddb"></a>
+ </td>
+ </tr>
+ </table>
+
+ [% PROCESS "global/common-links.html.tmpl" qs_suffix = "_top" %]
+
+ </div>
+
+[% ELSE %]
+
+[% INCLUDE global/banner.html.tmpl %]
+
+<table border="0" cellspacing="0" cellpadding="0" id="titles">
+<tr>
+ <td id="title">
+ <p>[% terms.BugzillaTitle %]
+ [% " &ndash; $header" FILTER none IF header %]</p>
+ </td>
+
+ [% IF subheader %]
+ <td id="subtitle">
+ <p class="subheader">[% subheader FILTER none %]</p>
+ </td>
+ [% END %]
+
+ [% IF header_addl_info %]
+ <td id="information">
+ <p class="header_addl_info">[% header_addl_info FILTER none %]</p>
+ </td>
+ [% END %]
+</tr>
+</table>
+
+<table id="lang_links_container" cellpadding="0" cellspacing="0"
+ class="bz_default_hidden"><tr><td>
+[% IF Bugzilla.languages.size > 1 %]
+ <ul class="links">
+ [% FOREACH lang = Bugzilla.languages.sort %]
+ <li>[% IF NOT loop.first %]<span class="separator"> | </span>[% END %]
+ [% IF lang == current_language %]
+ <span class="lang_current">[% lang FILTER html FILTER upper %]</span>
+ [% ELSE %]
+ <a href="#" onclick="set_language('[% lang FILTER none %]');">
+ [%- lang FILTER html FILTER upper %]</a>
+ [% END %]
+ </li>
+ [% END %]
+ </ul>
+[% END %]
+</td></tr></table>
+
+[% PROCESS "global/common-links.html.tmpl" qs_suffix = "_top" %]
+
+[% END %]
+
+</div> [%# header %]
+
+<div id="bugzilla-body">
+
+[% IF Param('announcehtml') %]
+[% Param('announcehtml') FILTER none %]
+[% END %]
+
+[% IF message %]
+<div id="message">[% message FILTER none %]</div>
+[% END %]
+
+[% BLOCK format_css_link %]
+ [% IF style_url.match('/IE-fixes\.css') %]
+ <!--[if lte IE 7]>
+ [%# Internet Explorer treats [if IE] HTML comments as uncommented.
+ # We use it to import CSS fixes so that Bugzilla looks decent on IE 7
+ # and below.
+ #%]
+ [% END %]
+
+ [% IF css_set_name == 'standard' %]
+ [% SET css_title_link = '' %]
+ [% ELSE %]
+ [% css_title_link = BLOCK ~%]
+ title="[% setting_descs.${user.settings.skin.value} || user.settings.skin.value FILTER html %]"
+ [% END %]
+ [% END %]
+
+ <link href="[% style_url FILTER html %]" rel="stylesheet"
+ type="text/css" [% css_title_link FILTER none %]>
+
+ [% '<![endif]-->' IF style_url.match('/IE-fixes\.css') %]
+[% END %]
+
+[% BLOCK format_js_link %]
+ <script type="text/javascript" src="[% javascript_url FILTER mtime FILTER html %]"></script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/global/prod-comp-search.html.tmpl b/extensions/BMO/template/en/default/global/prod-comp-search.html.tmpl
new file mode 100644
index 000000000..2f1d67bec
--- /dev/null
+++ b/extensions/BMO/template/en/default/global/prod-comp-search.html.tmpl
@@ -0,0 +1,43 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<div id="prod_comp_search_main">
+ <div id="prod_comp_search_autocomplete">
+ <div id="prod_comp_search_label">
+ Type to find product and component by name or description:
+ <img id="prod_comp_throbber" src="extensions/BMO/web/images/throbber.gif"
+ class="hidden" width="16" height="11">
+ </div>
+ <input id="prod_comp_search" type="text" size="60">
+ <div id="prod_comp_search_autocomplete_container"></div>
+ </div>
+</div>
+<script type="text/javascript">
+ if(typeof(YAHOO.bugzilla.prodCompSearch) !== 'undefined'
+ && YAHOO.bugzilla.prodCompSearch != null)
+ {
+ YAHOO.bugzilla.prodCompSearch.init(
+ "prod_comp_search",
+ "prod_comp_search_autocomplete_container",
+ "[% format FILTER js %]",
+ "[% cloned_bug_id FILTER js %]");
+ [% IF target == "describecomponents.cgi" %]
+ YAHOO.bugzilla.prodCompSearch.autoComplete.itemSelectEvent.subscribe(function (e, args) {
+ var oData = args[2];
+ var url = "describecomponents.cgi?product=" + encodeURIComponent(oData[0]) +
+ "&component=" + encodeURIComponent(oData[1]) +
+ "#" + encodeURIComponent(oData[1]);
+ var format = YAHOO.bugzilla.prodCompSearch.format;
+ if (format) {
+ url += "&format=" + encodeURIComponent(format);
+ }
+ window.location.href = url;
+ });
+ [% END %]
+ }
+</script>
diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl
new file mode 100644
index 000000000..3dc727b87
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl
@@ -0,0 +1,2 @@
+[% mimetypes.push({type => "image/svg+xml", desc => "SVG image"}) %]
+[% mimetypes.push({type => "application/vnd.mozilla.xul+xml", desc => "XUL"}) %] \ No newline at end of file
diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl
new file mode 100644
index 000000000..ea80fdc5e
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl
@@ -0,0 +1 @@
+<em>You can <a href="http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree">read about the patch submission and approval process</a>.</em><br>
diff --git a/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl
new file mode 100644
index 000000000..caf7acca7
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl
@@ -0,0 +1,19 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.id && comment.author.login_name == 'tbplbot@gmail.com' %]
+ [% has_tbpl_comment = 1 %]
+ <script>
+ var id = [% count FILTER none %];
+ tbpl_comment_ids.push(id);
+ collapse_comment(
+ document.getElementById('comment_link_' + id),
+ document.getElementById('comment_text_' + id)
+ );
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl
new file mode 100644
index 000000000..d8dc5bba0
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl
@@ -0,0 +1,42 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF has_tbpl_comment %]
+ [% expand_caption = 'Expand TinderboxPushlog Comments' %]
+ [% collapse_caption = 'Collapse TinderboxPushlog Comments' %]
+ <script>
+ YAHOO.util.Event.onDOMReady(function () {
+ var ul = document.getElementsByClassName('bz_collapse_expand_comments');
+ if (ul.length == 0)
+ return;
+ var li = document.createElement('li');
+ var a = document.createElement('a');
+ Dom.setAttribute(a, 'href', 'javascript:void(0)');
+ Dom.setAttribute(a, 'id', 'toggle_tbplbot_comments');
+ a.innerHTML = '[% expand_caption FILTER js %]';
+ YAHOO.util.Event.on(a, 'click', function() {
+ var do_expand = a.innerHTML == '[% expand_caption FILTER js %]';
+ for (var i = 0, n = tbpl_comment_ids.length; i < n; i++) {
+ var id = tbpl_comment_ids[i];
+ var link = document.getElementById('comment_link_' + id);
+ var text = document.getElementById('comment_text_' + id);
+ if (do_expand) {
+ expand_comment(link, text);
+ } else {
+ collapse_comment(link, text);
+ }
+ }
+ a.innerHTML = do_expand
+ ? '[% collapse_caption FILTER js %]'
+ : '[% expand_caption FILTER js %]';
+ });
+ li.appendChild(a);
+ ul[0].appendChild(li);
+ });
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl
new file mode 100644
index 000000000..2ae367456
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl
@@ -0,0 +1,13 @@
+[%# *** Disclaimer for Legal bugs *** %]
+[% IF bug.product == "Legal" %]
+ <div id="legal_disclaimer">
+ The material and information contained herein is Confidential and
+ subject to Attorney-Client Privilege and Work Product Doctrine.
+ </div>
+[% END %]
+
+[%# Needed for collapsing TinderboxPushlog comments %]
+[% has_tbpl_comment = 0 %]
+<script>
+ var tbpl_comment_ids = new Array();
+</script>
diff --git a/extensions/BMO/template/en/default/hook/bug/comments-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-end.html.tmpl
new file mode 100644
index 000000000..3bf18a515
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/comments-end.html.tmpl
@@ -0,0 +1,20 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.id && comment.author.login_name == 'tbplbot@gmail.com' %]
+ [% has_tbpl_comment = 1 %]
+ <script>
+ var id = [% count FILTER none %];
+ tbpl_comment_ids.push(id);
+ YAHOO.util.Dom.addClass(comment, 'collapsed');
+ collapse_comment(
+ document.getElementById('comment_link_' + id),
+ document.getElementById('comment_text_' + id)
+ );
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl
new file mode 100644
index 000000000..cbe921c76
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl
@@ -0,0 +1,40 @@
+ <tr>
+ <th>Security:</th>
+ <td colspan="3">
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+ [% PROCESS group_checkbox
+ name = sec_group
+ desc = "Many users could be harmed by this security problem: " _
+ "it should be kept hidden from the public until it is resolved."
+ %]
+ [% IF user.in_group('partner-confidential-visible') %]
+ [% PROCESS group_checkbox
+ name = 'partner-confidential'
+ desc = "Restrict the visibility of this " _ terms.bug _ " to " _
+ "the assignee, QA contact, and CC list only."
+ %]
+ [% END %]
+ [% IF user.in_group('mozilla-corporation-confidential-visible')
+ && !user.in_group('mozilla-corporation-confidential') %]
+ [% PROCESS group_checkbox
+ name = 'mozilla-corporation-confidential'
+ desc = "Restrict the visibility of this " _ terms.bug _ " to " _
+ "Mozilla Employees and Contractors only."
+ %]
+ [% END %]
+ <br>
+ </td>
+ </tr>
+
+[% BLOCK group_checkbox %]
+ <input type="checkbox" name="groups"
+ value="[% name FILTER none %]" id="group_[% name FILTER html %]"
+ [% FOREACH g = group %]
+ [% IF g.name == name %]
+ [% ' checked="checked"' IF g.checked %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+ >
+ <label for="group_[% name FILTER html %]">[% desc FILTER html %]</label><br>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl
new file mode 100644
index 000000000..a0fff4175
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl
@@ -0,0 +1,22 @@
+ <tr bgcolor="[% tablecolour FILTER html %]">
+ <td valign="middle" align="right">
+ <b>Security</b>
+ </td>
+ <td valign="top">
+ <p>
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+
+ <input type="checkbox" name="groups"
+ id="groups" value="[% sec_group FILTER none %]"
+ [% FOREACH g = group %]
+ [% IF g.name == sec_group %]
+ [% " checked=\"checked\"" IF g.checked %]
+ [% END %]
+ [% END %]
+ >
+ <label for="groups">
+ Many users could be harmed by this security problem: it should be kept
+ hidden from the public until it is resolved.</label>
+ </p>
+ </td>
+ </tr>
diff --git a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..f72267246
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,128 @@
+[%# ***** BEGIN LICENSE BLOCK *****
+ # Version: MPL 1.1
+ #
+ # The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is the BMO Bugzilla Extension;
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <glob@mozilla.com>
+ #
+ # ***** END LICENSE BLOCK *****
+ #%]
+
+[% tracking_flags = [] %]
+[% project_flags = [] %]
+[% FOREACH field = Bugzilla.active_custom_fields(product=>bug.product_obj,component=>bug.component_obj,type=>2) %]
+ [% NEXT IF NOT user.id AND bug.${field.name} == "---" %]
+ [% NEXT IF cf_flag_disabled(field.name, bug) %]
+ [% IF cf_is_project_flag(field.name) %]
+ [% project_flags.push(field) %]
+ [% ELSE %]
+ [% tracking_flags.push(field) %]
+ [% END %]
+[% END %]
+
+[% IF project_flags.size %]
+ <tr>
+ <th class="field_label">
+ <label>Project Flags:</label>
+ </td>
+ <td>
+ [% IF bug.check_can_change_field('flagtypes.name', 0, 1) %]
+ <table id="project-flags">
+ [% FOREACH field = project_flags %]
+ [% NEXT IF NOT user.id AND field.value == "---" %]
+ <tr id="row_[% field.name FILTER js %]">
+ <td>&nbsp;</td>
+ <td>
+ <label for="[% field.name FILTER html %]">
+ [% field_descs.${field.name} FILTER html %]:
+ </label>
+ </td>
+ <td>
+ [% PROCESS bug/field.html.tmpl value = bug.${field.name}
+ editable = user.id
+ no_tds = 1 %]
+ [% IF user.id %]
+ <span id="ro_[% field.name FILTER html %]" class="bz_hidden">
+ [% bug.${field.name} FILTER html %]
+ </span>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ [% ELSE %]
+ [% FOREACH field = project_flags %]
+ [% NEXT IF bug.${field.name} == "---" %]
+ [% field_descs.${field.name} FILTER html %]: [% bug.${field.name} FILTER html %]<br>
+ [% END %]
+ [% END %]
+ </td>
+ </tr>
+[% END %]
+
+[% IF tracking_flags.size %]
+ <tr>
+ <th class="field_label">
+ <label>Tracking Flags:</label>
+ </td>
+ <td>
+ [% IF bug.check_can_change_field('flagtypes.name', 0, 1) %]
+ [% IF user.id %]
+ <span id="edit_tracking_fields_action">
+ (<a onclick="bmo_show_tracking_flags()" href="javascript:void(0)">edit</a>)
+ </span>
+ [% END %]
+ <table id="custom-flags">
+ [% FOREACH field = tracking_flags %]
+ [% NEXT IF NOT user.id AND field.value == "---" %]
+ <tr id="row_[% field.name FILTER js %]">
+ <td>&nbsp;</td>
+ <td>
+ <label for="[% field.name FILTER html %]">
+ [% field_descs.${field.name} FILTER html %]:
+ </label>
+ </td>
+ <td>
+ [% PROCESS bug/field.html.tmpl value = bug.${field.name}
+ editable = user.id
+ no_tds = 1 %]
+ [% IF user.id %]
+ <span id="ro_[% field.name FILTER html %]" class="bz_hidden">
+ [% bug.${field.name} FILTER html %]
+ </span>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ [% ELSE %]
+ [% FOREACH field = tracking_flags %]
+ [% NEXT IF bug.${field.name} == "---" %]
+ [% field_descs.${field.name} FILTER html %]: [% bug.${field.name} FILTER html %]<br>
+ [% END %]
+ [% END %]
+ </td>
+ </tr>
+ <script type="text/javascript">
+ var bmo_custom_flags = new Array([% tracking_flags.size FILTER none %]);
+ [% FOREACH field = tracking_flags %]
+ bmo_custom_flags['[% field.name FILTER js %]'] = '[% bug.${field.name} FILTER js %]';
+ [% END %]
+ bmo_hide_tracking_flags();
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/edit-after_importance.html.tmpl b/extensions/BMO/template/en/default/hook/bug/edit-after_importance.html.tmpl
new file mode 100644
index 000000000..f3eebafd3
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/edit-after_importance.html.tmpl
@@ -0,0 +1,77 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%# Display product and component descriptions after their respective fields %]
+<script type="text/javascript">
+ var Event = YAHOO.util.Event;
+ var Dom = YAHOO.util.Dom;
+ Event.onDOMReady(function() {
+ // Display product description if user requests it
+ var prod_desc = '[% bug.product_obj.description FILTER html_light FILTER js %]';
+ if (prod_desc) {
+ var field_container = Dom.get('field_container_product');
+ var toggle_container = document.createElement('span');
+ Dom.setAttribute(toggle_container, 'id', 'toggle_prod_desc');
+ toggle_container.appendChild(document.createTextNode(' ('));
+ var toggle_link = document.createElement('a');
+ Dom.setAttribute(toggle_link, 'id', 'toggle_prod_desc_link');
+ Dom.setAttribute(toggle_link, 'href', 'javascript:void(0);')
+ toggle_link.appendChild(document.createTextNode('show info'));
+ toggle_container.appendChild(toggle_link);
+ toggle_container.appendChild(document.createTextNode(')'));
+ field_container.appendChild(toggle_container);
+ var desc_container = document.createElement('div');
+ Dom.setAttribute(desc_container, 'id', 'prod_desc_container');
+ Dom.addClass(desc_container, 'bz_default_hidden');
+ desc_container.innerHTML = prod_desc;
+ field_container.appendChild(desc_container);
+ Event.addListener(toggle_link, 'click', function () {
+ if (Dom.hasClass('prod_desc_container', 'bz_default_hidden')) {
+ Dom.get('toggle_prod_desc_link').innerHTML = 'hide info';
+ Dom.removeClass('prod_desc_container', 'bz_default_hidden');
+ }
+ else {
+ Dom.get('toggle_prod_desc_link').innerHTML = 'show info';
+ Dom.addClass('prod_desc_container', 'bz_default_hidden');
+ }
+ });
+ }
+
+ // Display component description if user requests it
+ var comp_desc = '[% bug.component_obj.description FILTER html_light FILTER js %]';
+ if (comp_desc) {
+ var field_container = Dom.get('field_container_component');
+ var toggle_container = document.createElement('span');
+ Dom.setAttribute(toggle_container, 'id', 'toggle_comp_desc');
+ toggle_container.appendChild(document.createTextNode(' ('));
+ var toggle_link = document.createElement('a');
+ Dom.setAttribute(toggle_link, 'id', 'toggle_comp_desc_link');
+ Dom.setAttribute(toggle_link, 'href', 'javascript:void(0);')
+ toggle_link.appendChild(document.createTextNode('show info'));
+ toggle_container.appendChild(toggle_link);
+ toggle_container.appendChild(document.createTextNode(')'));
+ field_container.appendChild(toggle_container);
+ var desc_container = document.createElement('div');
+ Dom.setAttribute(desc_container, 'id', 'comp_desc_container');
+ Dom.addClass(desc_container, 'bz_default_hidden');
+ desc_container.innerHTML = comp_desc;
+ field_container.appendChild(desc_container);
+ Event.addListener(toggle_link, 'click', function () {
+ console.log('clicked');
+ if (Dom.hasClass('comp_desc_container', 'bz_default_hidden')) {
+ Dom.get('toggle_comp_desc_link').innerHTML = 'hide info';
+ Dom.removeClass('comp_desc_container', 'bz_default_hidden');
+ }
+ else {
+ Dom.get('toggle_comp_desc_link').innerHTML = 'show info';
+ Dom.addClass('comp_desc_container', 'bz_default_hidden');
+ }
+ });
+ }
+ });
+</script>
diff --git a/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl
new file mode 100644
index 000000000..dda75a9c6
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl
@@ -0,0 +1,96 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% USE Bugzilla %]
+[% IF Bugzilla.request_cache.bmo_fields_page %]
+ [%
+ vars.help_html.priority =
+ "This field describes the importance and order in which $terms.abug
+ should be fixed compared to other ${terms.bugs}. This field is utilized
+ by the programmers/engineers to prioritize their work to be done where
+ P1 is considered the highest and P5 is the lowest."
+
+ vars.help_html.bug_severity =
+ "This field describes the impact of ${terms.abug}.
+ <table>
+ <tr>
+ <th>blocker</th>
+ <td>Blocks development and/or testing work</td>
+ </tr>
+ <tr>
+ <th>critical</th>
+ <td>crashes, loss of data, severe memory leak</td>
+ </tr>
+ <tr>
+ <th>major</th>
+ <td>major loss of function</td>
+ </tr>
+ <tr>
+ <th>normal</th>
+ <td>regular issue, some loss of functionality under specific circumstances</td>
+ </tr>
+ <tr>
+ <th>minor</th>
+ <td>minor loss of function, or other problem where easy
+ workaround is present</td>
+ </tr>
+ <tr>
+ <th>trivial</th>
+ <td>cosmetic problem like misspelled words or misaligned
+ text</td>
+ </tr>
+ <tr>
+ <th>enhancement</th>
+ <td>Request for enhancement</td>
+ </table>"
+
+ vars.help_html.rep_platform =
+ "This is the hardware platform against which the $terms.bug was reported.
+ Legal platforms include:
+ <ul>
+ <li>All (happens on all platforms; cross-platform ${terms.bug})</li>
+ <li>x86_64</li>
+ <li>ARM</li>
+ </ul>
+ <b>Note:</b> When searching, selecting the option
+ <em>All</em> does not
+ select $terms.bugs assigned against any platform. It merely selects
+ $terms.bugs that are marked as occurring on all platforms, i.e. are
+ designated <em>All</em>.",
+
+ vars.help_html.op_sys =
+ "This is the operating system against which the $terms.bug was
+ reported. Legal operating systems include:
+ <ul>
+ <li>All (happens on all operating systems; cross-platform ${terms.bug})</li>
+ <li>Windows 7</li>
+ <li>Mac OS X</li>
+ <li>Linux</li>
+ </ul>
+ Sometimes the operating system implies the platform, but not
+ always. For example, Linux can run on x86_64, ARM, and others.",
+
+ vars.help_html.assigned_to =
+ "This is the person in charge of resolving the ${terms.bug}. Every time
+ this field changes, the status changes to
+ <b>NEW</b> to make it
+ easy to see which new $terms.bugs have appeared on a person's list.</p>",
+ %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl b/extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl
new file mode 100644
index 000000000..a99b4f9f6
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% title = title.replace('^' _ terms.Bug _ ' ', '') %]
diff --git a/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..5ab189045
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,18 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% style_urls.push('extensions/BMO/web/styles/edit_bug.css') %]
+[% javascript_urls.push('extensions/BMO/web/js/edit_bug.js') %]
+[% title = "$bug.bug_id &ndash; " %]
+[% IF bug.alias != '' %]
+ [% title = title _ "($bug.alias) " %]
+[% END %]
+[% title = title _ filtered_desc %]
+[% javascript = javascript _
+ "document.title = document.title.replace(/^" _ terms.Bug _ " /, '');"
+%]
diff --git a/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl b/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl
new file mode 100644
index 000000000..8c543b35d
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF in_template_var %]
+ [% vars.field_descs.cc_count = "CC Count" %]
+ [% vars.field_descs.dupe_count = "Duplicate Count" %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl
new file mode 100644
index 000000000..b5bb4719c
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl
@@ -0,0 +1 @@
+<a href="https://www.mozilla.org/about/policies/privacy-policy.html">Privacy Policy</a>
diff --git a/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl
new file mode 100644
index 000000000..5f8965d5d
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl
@@ -0,0 +1,67 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMOHeader Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Reed Loden.
+ # Portions created by the Initial Developer are Copyright (C) 2010 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+<link rel="shortcut icon" href="extensions/BMO/web/images/favicon.ico">
+[% IF bug %]
+<link id="shorturl" rev="canonical" href="https://bugzil.la/[% bug.bug_id FILTER uri %]">
+[% END %]
+
+[%# *** Bug List Navigation *** %]
+[% IF bug %]
+ [% SET my_search = user.recent_search_for(bug) %]
+ [% IF my_search %]
+ [% SET last_bug_list = my_search.bug_list %]
+ [% SET this_bug_idx = lsearch(last_bug_list, bug.id) %]
+ <link rel="Up" href="buglist.cgi?regetlastlist=
+ [%- my_search.id FILTER uri %]">
+ <link rel="First" href="show_bug.cgi?id=
+ [%- last_bug_list.first FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ <link rel="Last" href="show_bug.cgi?id=
+ [%- last_bug_list.last FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% IF this_bug_idx > 0 %]
+ [% prev_bug = this_bug_idx - 1 %]
+ <link rel="Prev" href="show_bug.cgi?id=
+ [%- last_bug_list.$prev_bug FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% END %]
+ [% IF this_bug_idx + 1 < last_bug_list.size %]
+ [% next_bug = this_bug_idx + 1 %]
+ <link rel="Next" href="show_bug.cgi?id=
+ [%- last_bug_list.$next_bug FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% END %]
+ [% END %]
+[% END %]
+
+[% IF urlbase == 'https://bugzilla.mozilla.org/' %]
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-36116321-3']);
+ _gaq.push(['_trackPageview']);
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl
new file mode 100644
index 000000000..e265d0bb6
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl
@@ -0,0 +1,40 @@
+[% IF !javascript_urls %]
+ [% javascript_urls = [] %]
+[% END %]
+
+[% IF template.name == 'list/list.html.tmpl' %]
+ [% javascript_urls.push('extensions/BMO/web/js/sorttable.js') %]
+[% END %]
+
+[% IF !bodyclasses %]
+ [% bodyclasses = [] %]
+[% END %]
+
+[%# Change the background/border for bugs/attachments in certain bug groups %]
+[% IF template.name == 'attachment/edit.html.tmpl'
+ || template.name == 'attachment/create.html.tmpl'
+ || template.name == 'attachment/diff-header.html.tmpl' %]
+ [% style_urls.push("skins/custom/bug_groups.css") %]
+
+ [% IF template.name == 'attachment/edit.html.tmpl'
+ || template.name == 'attachment/diff-header.html.tmpl' %]
+ [% IF bodyclasses == 'no_javascript' %]
+ [% bodyclasses = ['no_javascript'] %]
+ [% END %]
+ [% FOREACH group = attachment.bug.groups_in %]
+ [% bodyclasses.push("bz_group_$group.name") %]
+ [% END %]
+ [% END %]
+
+ [% IF template.name == 'attachment/create.html.tmpl' %]
+ [% FOREACH group = bug.groups_in %]
+ [% bodyclasses.push("bz_group_$group.name") %]
+ [% END %]
+ [% END %]
+[% END %]
+
+[% IF user.in_group('canconfirm') %]
+ [% yui.push('container', 'menu') %]
+ [% style_urls.push('js/yui/assets/skins/sam/menu.css') %]
+ [% javascript_urls.push('extensions/BMO/web/js/edituser_menu.js') %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl b/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl
new file mode 100644
index 000000000..0c90b97b9
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl
@@ -0,0 +1,5 @@
+[% IF message_tag == "employee_incident_creation_failed" %]
+ The [% terms.bug %] was created successfully, but the dependent
+ Employee Incident [% terms.bug %] creation failed. The error has
+ been logged and no further action is required at this time.
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl
new file mode 100644
index 000000000..666621d8b
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl
@@ -0,0 +1,5 @@
+[%
+ setting_descs.product_chooser = "Product chooser to use when entering bugs",
+ setting_descs.pretty_product_chooser = "Pretty chooser with common products and icons",
+ setting_descs.full_product_chooser = "Full chooser with all products",
+%]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
new file mode 100644
index 000000000..0a674aa30
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
@@ -0,0 +1,5 @@
+[% IF object == 'group_admins' %]
+ the group administrators report
+[% ELSIF object == 'email_queue' %]
+ the email queue status report
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error-error_message.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-error_message.html.tmpl
new file mode 100644
index 000000000..de1848495
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error-error_message.html.tmpl
@@ -0,0 +1,15 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == 'illegal_change' || error == 'illegal_change_deps' %]
+ <p>
+ If you are attempting to confirm an unconfirmed [% terms.bug %] or edit the
+ fields of a [% terms.bug %], <a href="page.cgi?id=get_permissions.html">find
+ out how to get the necessary permissions</a>.
+ </p>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..eff0e35cc
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,36 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <bjones@mozilla.com>
+ #%]
+
+[% IF error == "user_activity_missing_username" %]
+ [% title = "Missing Username" %]
+ You must provide at least one email address to report on.
+
+[% ELSIF error == "report_invalid_date" %]
+ [% title = "Invalid Date" %]
+ The date '[% date FILTER html %]' is invalid.
+
+[% ELSIF error == "report_invalid_parameter" %]
+ [% title = "Invalid Parameter" %]
+ The value for parameter [% name FILTER html %] is invalid.
+
+[% ELSIF error == "invalid_object" %]
+ Invalid [% object FILTER html %]: "[% value FILTER html %]"
+
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl
new file mode 100644
index 000000000..346e02373
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl
@@ -0,0 +1,29 @@
+<!-- 1.0@bugzilla.org -->
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+[% IF (group == "canconfirm" OR group == "editbugs") AND !reason %]
+ <p>
+ If you are attempting to confirm an unconfirmed [% terms.bug %] or edit the fields of a [% terms.bug %],
+ <a href="http://www.gerv.net/hacking/before-you-mail-gerv.html#bugzilla-permissions">find
+ out how to get the necessary permissions</a>.
+ </p>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl
new file mode 100644
index 000000000..89eef6fc4
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl
@@ -0,0 +1,3 @@
+[%
+ terms.BugzillaTitle = "Bugzilla@Mozilla"
+%]
diff --git a/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl
new file mode 100644
index 000000000..3ca61b7b1
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl
@@ -0,0 +1,15 @@
+<li>
+|
+<a href="page.cgi?id=etiquette.html">
+ [%- terms.Bugzilla %] Etiquette</a>
+</li>
+<li>
+|
+<a href="https://developer.mozilla.org/en/Bug_writing_guidelines">
+ [%- terms.Bug %] Writing Guidelines</a>
+</li>
+<li>
+|
+<a href="page.cgi?id=researchers.html">
+ Data for Researchers</a>
+</li>
diff --git a/extensions/BMO/template/en/default/hook/index-intro.html.tmpl b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl
new file mode 100644
index 000000000..d81d91491
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl
@@ -0,0 +1,2 @@
+<a id="get_help" class="bz_common_actions"
+ href="page.cgi?id=get_help.html"><span>Get Help</span></a> \ No newline at end of file
diff --git a/extensions/BMO/template/en/default/hook/pages/fields-open-status.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-open-status.html.tmpl
new file mode 100644
index 000000000..8f3407aa7
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/pages/fields-open-status.html.tmpl
@@ -0,0 +1,11 @@
+<dt>
+ <b>[% display_value("bug_status", "READY") FILTER html %]</b>
+</dt>
+<dd>
+ This [% terms.bug %] has enough information so that the developer can
+ start working on a fix. The [% terms.bug %] has the required testcases,
+ crash data, detailed specs, etc. [% terms.Bugs %] in this state may be
+ accepted, and become <b>[% display_value("bug_status", "ASSIGNED") FILTER html %]</b>,
+ passed on to someone else, and remain <b>[% display_value("bug_status", "READY") FILTER html %]</b>,
+ or resolved and marked <b>[% display_value("bug_status", "RESOLVED") FILTER html %]</b>.
+</dd>
diff --git a/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl
new file mode 100644
index 000000000..4d12ab345
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl
@@ -0,0 +1,13 @@
+<dt>
+ [% display_value("resolution", "INCOMPLETE") FILTER html %]
+</dt>
+<dd>
+ The problem is vaguely described with no steps to reproduce,
+ or is a support request. The reporter should be directed to the
+ product's support page for help diagnosing the issue. If there
+ are only a few comments in the [% terms.bug %], it may be reopened only if
+ the original reporter provides more info, or confirms someone
+ else's steps to reproduce. If the [% terms.bug %] is long, when enough info
+ is provided a new [% terms.bug %] should be filed and the original [% terms.bug %]
+ marked as a duplicate of it.
+</dd>
diff --git a/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl
new file mode 100644
index 000000000..35644c1e4
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl
@@ -0,0 +1,52 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<h2>Other Reports</h2>
+
+<ul>
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=user_activity.html">User Changes</a>
+ </strong> - Show changes made by an individual user.
+ </li>
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=triage_reports.html">Triage Report</a>
+ </strong> - Report on UNCONFIRMED [% terms.bugs %] to assist triage.
+ </li>
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=release_tracking_report.html">Release Tracking Report</a>
+ </strong> - For triaging release-train flag information.
+ </li>
+ [% IF user.in_group('editusers') || user.in_group('infrasec') %]
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=group_admins.html">Group Admins</a>
+ </strong> - Lists the administrators of each group.
+ </li>
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=group_membership.html">Group Membership Report</a>
+ </strong> - Lists the groups a user is a member of.
+ </li>
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=group_members.html">Group Members Report</a>
+ </strong> - Lists the users of groups.
+ </li>
+ [% END %]
+ [% IF user.in_group('admin') || user.in_group('infra') %]
+ <li>
+ <strong>
+ <a href="[% urlbase FILTER none %]page.cgi?id=email_queue.html">Email Queue</a>
+ </strong> - TheSchwartz queue
+ </li>
+ [% END %]
+</ul>
+
diff --git a/template/en/default/global/help.html.tmpl b/extensions/BMO/template/en/default/list/list.microsummary.tmpl
index c0ff819ce..8925db8dd 100644
--- a/template/en/default/global/help.html.tmpl
+++ b/extensions/BMO/template/en/default/list/list.microsummary.tmpl
@@ -1,3 +1,4 @@
+[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
@@ -15,19 +16,14 @@
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
- # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Contributor(s): Ronaldo Maia <rmaia@everythingsolved.com>
#%]
-[% USE Bugzilla %]
-[% cgi = Bugzilla.cgi %]
+[% PROCESS global/variables.none.tmpl %]
-[% IF cgi.param("help") %]
- <script type="text/javascript"> <!--
- [% FOREACH help_name = help_html.keys %]
- g_helpTexts["[% help_name FILTER js %]"] =
- "[%- help_html.$help_name FILTER js -%]";
- [% END %]
- // -->
- </script>
-[% END %]
+[% IF searchname %]
+ [% searchname FILTER html %] ([% bugs.size %])
+[% ELSE %]
+ [% terms.Bug %] List ([% bugs.size %])
+[% END %]
diff --git a/extensions/BMO/template/en/default/list/server-push.html.tmpl b/extensions/BMO/template/en/default/list/server-push.html.tmpl
new file mode 100644
index 000000000..1c1f3cf36
--- /dev/null
+++ b/extensions/BMO/template/en/default/list/server-push.html.tmpl
@@ -0,0 +1,52 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Myk Melez <myk@mozilla.org>
+ #%]
+
+[%# INTERFACE:
+ # debug: boolean. True if we want the search displayed while we wait.
+ # query: string. The SQL query which makes the buglist.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+<html>
+ <head>
+ <title>[% terms.Bugzilla %] is pondering your search</title>
+ </head>
+ <body>
+ <div style="margin-top: 15%; text-align: center;">
+ <center><img src="extensions/BMO/web/images/mozchomp.gif" alt=""
+ width="160" height="87"></center>
+ <h1>Please wait while your [% terms.bugs %] are retrieved.</h1>
+ </div>
+
+ [% IF debug %]
+ <p>
+ [% FOREACH debugline = debugdata %]
+ <code>[% debugline FILTER html %]</code><br>
+ [% END %]
+ </p>
+ <p>
+ <code>[% query FILTER html %]</code>
+ </p>
+ [% END %]
+
+ </body>
+</html>
diff --git a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
new file mode 100644
index 000000000..f326d1821
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
@@ -0,0 +1,25 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): David Lawrence <dkl@mozilla.com>
+ #%]
+
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0;url=https://developer.mozilla.org/en/Bug_writing_guidelines">
+ </head>
+</html>
diff --git a/extensions/BMO/template/en/default/pages/email_queue.html.tmpl b/extensions/BMO/template/en/default/pages/email_queue.html.tmpl
new file mode 100644
index 000000000..5c7970506
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/email_queue.html.tmpl
@@ -0,0 +1,66 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Job Queue Status"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+%]
+
+[% IF jobs.size %]
+
+ <p><i>[% jobs.size FILTER none %] email(s) in the queue.</i></p>
+
+ <table id="report" class="hover" cellspacing="0" border="0">
+ <tr id="report-header">
+ <th>Insert Time</th>
+ <th>Run Time</th>
+ <th>Age</th>
+ <th>Error Count</th>
+ <th>Last Error</th>
+ <th>Error Message</th>
+ </tr>
+ [% FOREACH job IN jobs %]
+ <tr class="report item [% loop.count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td nowrap>[% time2str("%Y-%m-%d %H:%M:%S %Z", job.insert_time) FILTER html %]</td>
+ <td nowrap>[% time2str("%Y-%m-%d %H:%M:%S %Z", job.run_time) FILTER html %]</td>
+ <td nowrap>
+ [% age = now - job.insert_time %]
+ [% IF age < 60 %]
+ [% age FILTER none %]s
+ [% ELSIF age < 60 * 60 %]
+ [% age / 60 FILTER format('%.0f') %]m
+ [% ELSE %]
+ [% age / (60 * 60) FILTER format('%.0f') %]h
+ [% END %]
+ </td>
+ <td nowrap>[% job.error_count FILTER html %]</td>
+ <td nowrap>
+ [% IF job.error_count %]
+ [% time2str("%Y-%m-%d %H:%M:%S %Z", job.error_time) FILTER html %]
+ [% ELSE %]
+ -
+ [% END %]
+ </td>
+ <td>
+ [% IF job.error_count %]
+ [% job.error_message FILTER html %]
+ [% ELSE %]
+ -
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+[% ELSE %]
+
+<p><i>The email queue is empty.</i></p>
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
new file mode 100644
index 000000000..78cc0bad7
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
@@ -0,0 +1,146 @@
+<!-- 1.0@bugzilla.org -->
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Stefan Seifert <nine@detonation.org>
+ # Gervase Markham <gerv@gerv.net>
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Bugzilla Etiquette"
+ style = "li { margin: 5px } .heading { font-weight: bold }" %]
+
+<p>
+ There's a number of <i lang="fr">faux pas</i> you can commit when using
+ [%+ terms.Bugzilla %]. At the very
+ least, these will make Mozilla contributors upset at you; if committed enough
+ times they will cause those contributors to demand the disabling of your
+ [%+ terms.Bugzilla %] account. So, ignore this advice at your peril.
+</p>
+
+<p>
+ That said, Mozilla developers are generally a friendly bunch, and will be
+ friendly towards you as long as you follow these guidelines.
+</p>
+
+<h3>1. Commenting</h3>
+
+<p>
+ This is the most important section.
+</p>
+
+<ol>
+ <li>
+ <span class="heading">No pointless comments</span>.
+ Unless you have something constructive and helpful to say, do not add a
+ comment to a [% terms.bug %]. In [% terms.bugs %] where there is a heated debate going on, you
+ should be even more
+ inclined not to add a comment. Unless you have something new to contribute,
+ then the [% terms.bug %] owner is aware of all the issues, and will make a judgement
+ as to what to do. If you agree the [% terms.bug %] should be fixed, vote for it.
+ Additional "I see this too" or "It works for me" comments are unnecessary
+ unless they are on a different platform or a significantly different build.
+ Constructive and helpful thoughts unrelated to the topic of the [% terms.bug %]
+ should go in the appropriate
+ <a href="http://www.mozilla.org/about/forums/">newsgroup</a>.
+ </li>
+
+ <li>
+ <span class="heading">No obligation</span>.
+ "Open Source" is not the same as "the developers must do my bidding."
+ Everyone here wants to help, but no one else has any <i>obligation</i> to fix
+ the [% terms.bugs %] you want fixed. Therefore, you should not act as if you
+ expect someone to fix a [% terms.bug %] by a particular date or release.
+ Aggressive or repeated demands will not be received well and will almost
+ certainly diminish the impact and interest in your suggestions.
+ </li>
+
+ <li>
+ <span class="heading">No abusing people</span>.
+ Constant and intense critique is one of the reasons we build great products.
+ It's harder to fall into group-think if there is always a healthy amount of
+ dissent. We want to encourage vibrant debate inside of the Mozilla
+ community, we want you to disagree with us, and we want you to effectively
+ argue your case. However, we require that in the process, you attack
+ <i>things</i>, not <i>people</i>. Examples of things include: interfaces,
+ algorithms, and schedules. Examples of people include: developers,
+ designers and users. <b>Attacking a person may result in you being banned
+ from [% terms.Bugzilla %].</b>
+ </li>
+
+ <li>
+ <span class="heading">No private email</span>.
+ Unless the [% terms.bug %] owner or another respected project contributor has asked you
+ to email them with specific information, please place all information
+ relating to [% terms.bugs %]
+ in the [% terms.bug %] itself. Do not send them by private email; no-one else can read
+ them if you do that, and they'll probably just get ignored. If a file
+ is too big for [% terms.Bugzilla %], add a comment giving the file size and contents
+ and ask what to do.
+ </li>
+</ol>
+
+<h3>2. Changing Fields</h3>
+
+<ol>
+ <li>
+ <span class="heading">No messing with other people's [% terms.bugs %]</span>.
+ Unless you are the [% terms.bug %] assignee, or have some say over the use of their
+ time, never change the Priority or Target Milestone fields. If in doubt,
+ do not change the fields of [% terms.bugs %] you do not own - add a comment
+ instead, suggesting the change.
+ </li>
+
+ <li>
+ <span class="heading">No whining about decisions</span>.
+ If a respected project contributor has marked a [% terms.bug %] as INVALID, then it is
+ invalid. Someone filing another duplicate of it does not change this. Unless
+ you have further important evidence, do not post a comment arguing that an
+ INVALID or WONTFIX [% terms.bug %] should be reopened.
+ </li>
+
+</ol>
+
+<h3>3. Applicability</h3>
+
+<ol>
+ <li>
+ Some of these rules may not apply to you. If they do not, you will know
+ exactly which ones do not, and why they do not apply. If you are not
+ sure, then they definitely all apply to you.
+ </li>
+</ol>
+
+<p>
+ If you see someone not following these rules, the first step is, as an exception
+ to guideline 1.4, to make them aware of this document by <em>private</em> mail.
+ Flaming people publically in [% terms.bugs %] violates guidelines 1.1 and 1.3. In the case of
+ persistent offending you should ping an administrator on Mozilla IRC in channel #bmo and ask them
+ to look into it.
+</p>
+
+<p>
+ This entire document can be summed up in one sentence:
+ do unto others as you would have them do unto you.
+</p>
+
+<p>
+ Other useful documents:
+ <a href="page.cgi?id=bug-writing.html">The [% terms.Bug %] Writing Guidelines</a>.
+</p>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/get_help.html.tmpl b/extensions/BMO/template/en/default/pages/get_help.html.tmpl
new file mode 100644
index 000000000..70ff0a12b
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/get_help.html.tmpl
@@ -0,0 +1,42 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): David Miller <justdave@bugzilla.org>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% INCLUDE global/header.html.tmpl title = "Get Help with Mozilla Products" %]
+
+<div id="steps">
+<h2>Got a problem?</h2>
+
+<ul>
+<li><a href="http://www.mozilla.org/support/">Get help with your mozilla.org product</a></li>
+<li><a href="http://hendrix.mozilla.org/">Leave quick feedback</a></li>
+<li><a href="http://input.mozilla.com/feedback">Report a broken website</a></li>
+<li><a href="enter_bug.cgi">Report a [% terms.bug %]</a> - latest release only
+ [% IF NOT user.id %]
+ (you'll need an
+ <a href="createaccount.cgi">account</a>)
+ [% END %]
+</li>
+</ul>
+</div>
+
+<br>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/get_permissions.html.tmpl b/extensions/BMO/template/en/default/pages/get_permissions.html.tmpl
new file mode 100644
index 000000000..b70aa488f
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/get_permissions.html.tmpl
@@ -0,0 +1,44 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Upgrade Permissions"
+%]
+
+<h3>How to apply for upgraded permissions</h3>
+
+<p>
+ If you want <kbd>canconfirm</kbd>, email <a href="mailto:bmo-perms@mozilla.org">
+ bmo-perms@mozilla.org</a> the URLs of three good [% terms.bug %] reports you have filed.
+</p>
+
+<p>
+ If you want <kbd>editbugs</kbd>, email <a href="mailto:bmo-perms@mozilla.org">
+ bmo-perms@mozilla.org</a> either:
+ <ul>
+ <li>
+ The URLs of two [% terms.bugs %] to which you have attached patches
+ or testcases; or
+ </li>
+ <li>
+ The URLs of the relevant comment on three [% terms.bugs %] which you
+ wanted to change, but couldn't, and so added a comment instead.
+ </li>
+ </ul>
+</p>
+
+<p>
+ <kbd>editbugs</kbd> implies <kbd>canconfirm</kbd>; there's no need to apply for both.
+</p>
+
+<p>
+ Don't forget to include your [% terms.Bugzilla %] ID if it's not the email address
+ you are emailing from.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
new file mode 100644
index 000000000..01bb744c4
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
@@ -0,0 +1,54 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Group Admins Report"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+ yui = [ "datasource" ]
+%]
+
+[% IF groups.size > 0 %]
+ <table border="0" cellspacing="0" id="report" class="hover" width="100%">
+ <tr id="report-header">
+ <th align="left">Name</th>
+ <th align="left">Admins</th>
+ </tr>
+
+ [% FOREACH group = groups %]
+ [% count = loop.count() %]
+ <tr class="report_item [% count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td>
+ [% group.name FILTER html %]
+ </td>
+ <td>
+ [% FOREACH admin = group.admins %]
+ [% INCLUDE global/user.html.tmpl who = admin %][% ", " UNLESS loop.last %]
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+[% ELSE %]
+ <p>
+ No groups found.
+ </p>
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_members.html.tmpl b/extensions/BMO/template/en/default/pages/group_members.html.tmpl
new file mode 100644
index 000000000..daf4d5b0d
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_members.html.tmpl
@@ -0,0 +1,97 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Group Members Report"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+%]
+
+<form method="GET" action="page.cgi">
+ <input type="hidden" name="id" value="group_members.html">
+
+ <table id="parameters">
+ <tr>
+ <th>Group</th>
+ <td>
+ <select name="group">
+ [% FOREACH group_name = groups %]
+ <option value="[% group_name FILTER html %]"
+ [% "selected" IF group_name == group %]>
+ [% group_name FILTER html %]</option>
+ [% END %]
+ </select>
+ <input type="checkbox" name="include_disabled" id="include_disabled"
+ value="1" [% "checked" IF include_disabled %]>
+ <label for="include_disabled">
+ Include disabled users
+ </label>
+ <input type="submit" value="Generate">
+ </td>
+ </tr>
+ </table>
+</form>
+
+[% IF group != '' %]
+
+ <p>
+ Members of the <b>[% group FILTER html %]</b> group:
+ </p>
+
+ [% IF types.size > 0 %]
+ <table border="0" cellspacing="0" id="report" class="nohover" width="100%">
+ <tr id="report-header">
+ <th>Type</th>
+ <th>Count</th>
+ <th>Members</th>
+ <th class="right">Last Seen (days ago)</th>
+ </tr>
+
+ [% FOREACH type = types %]
+ [% count = loop.count() %]
+ <tr class="report_item [% count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td valign="top">
+ [% "via&nbsp;" UNLESS type.name == 'direct' %]
+ [% type.name FILTER html %]
+ </td>
+ <td valign="top" align="right">
+ [% type.members.size FILTER html %]
+ </td>
+ <td valign="top" width="100%" colspan="2">
+ <table cellspacing="0" class="hoverrow">
+ [% FOREACH member = type.members %]
+ <tr>
+ <td width="100%">
+ <a href="editusers.cgi?action=edit&amp;userid=[% member.id FILTER none %]"
+ target="_blank">
+ <span [% 'class="bz_inactive"' UNLESS member.is_enabled %]>
+ [% member.name FILTER html %] &lt;[% member.email FILTER email FILTER html %]&gt;
+ </span>
+ </a>
+ </td>
+ <td align="right" nowrap>
+ [% member.lastseen FILTER html %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+ <a href="page.cgi?id=group_members.json&amp;group=[% group FILTER uri %]
+ [% IF include_disabled %]&amp;include_disabled=1[% END %]">JSON</a>
+ [% ELSE %]
+ <p>
+ <i>This group is empty.</i>
+ </p>
+ [% END %]
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_members.json.tmpl b/extensions/BMO/template/en/default/pages/group_members.json.tmpl
new file mode 100644
index 000000000..f80fc8c5f
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_members.json.tmpl
@@ -0,0 +1,32 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[
+ [% SET count = 0 %]
+ [% FOREACH type = types %]
+ [% SET count = count + type.members.size %]
+ [% END %]
+ [% SET i = 0 %]
+ [% FOREACH type = types %]
+ [% FOREACH member = type.members %]
+ [% SET i = i + 1 %]
+ { "login": "[% member.login FILTER email FILTER js %]",
+ [% IF type.name == "direct" %]
+ "membership": "direct",
+ [% ELSE %]
+ "membership": "indirect",
+ "group": [% type.name FILTER js %]",
+ [% END %]
+ [% IF include_disabled %]
+ "disabled": "[% member.is_enabled ? "false" : "true" %]",
+ [% END %]
+ "lastseen": "[% member.lastseen FILTER js %]"
+ }[% "," UNLESS i == count %]
+ [% END %]
+ [% END %]
+]
diff --git a/extensions/BMO/template/en/default/pages/group_membership.html.tmpl b/extensions/BMO/template/en/default/pages/group_membership.html.tmpl
new file mode 100644
index 000000000..32484b13f
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_membership.html.tmpl
@@ -0,0 +1,75 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Group Membership Report"
+ yui = [ 'autocomplete' ]
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+ javascript_urls = [ "js/field.js" ]
+%]
+
+<form method="GET" action="page.cgi">
+<input type="hidden" name="id" id="id" value="group_membership.html">
+
+<table id="parameters">
+<tr>
+ <th>User(s):</th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "who"
+ name => "who"
+ value => who.join(', ')
+ size => 40
+ classes => ["bz_userfield"]
+ multiple => 5
+ field_title => "One or more email address (comma delimited)"
+ %]
+ </td>
+ <td>&nbsp;</td>
+ <td>
+ <select name="output"
+ onchange="document.getElementById('id').value = 'group_membership.' + this.value">
+ <option value="html" [% 'selected' IF output == 'html' %]>HTML</option>
+ <option value="txt" [% 'selected' IF output == 'txt' %]>Text</option>
+ </select>
+ </td>
+ <td>
+ <input type="submit" value="Generate">
+ </td>
+</tr>
+</table>
+
+</form>
+
+[% IF users.size %]
+
+ <table border="0" cellspacing="0" id="report" class="hover" width="100%">
+ [% FOREACH u = users %]
+ <tr>
+ <th colspan="3">[% u.user.identity FILTER html %]</th>
+ </tr>
+ [% FOREACH g = u.groups %]
+ <tr>
+ <td>&nbsp;</td>
+ <td>[% g.name FILTER html %]</td>
+ <td>[% g.desc FILTER html %]</td>
+ <td>
+ [% IF g.via == '' %]
+ direct
+ [% ELSE %]
+ <i>[% g.via FILTER html %]</i>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ [% END %]
+ </table>
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl b/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl
new file mode 100644
index 000000000..9958f0877
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl
@@ -0,0 +1,16 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% FOREACH u = users %]
+[% u.user.login FILTER none%]:
+ [% FOREACH g = u.groups %]
+ [% g.name FILTER none %]
+ [% ',' UNLESS loop.last %]
+ [% END %]
+ [% "\n" %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/pages/query_database.html.tmpl b/extensions/BMO/template/en/default/pages/query_database.html.tmpl
new file mode 100644
index 000000000..97f5c0a25
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/query_database.html.tmpl
@@ -0,0 +1,47 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Query Database"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+%]
+
+<form method="post" action="page.cgi">
+<input type="hidden" name="id" value="query_database.html">
+<textarea cols="80" rows="10" name="query">[% query FILTER html %]</textarea><br>
+<input type="submit" value="Execute">
+</form>
+
+[% IF executed %]
+ <hr>
+
+ [% IF sql_error %]
+ <b>[% sql_error FILTER html %]</b>
+ [% ELSIF rows.size %]
+ <table border="0" cellspacing="0" id="report">
+ <tr>
+ [% FOREACH column = columns %]
+ <th>[% column FILTER html %]</th>
+ [% END %]
+ </tr>
+ [% FOREACH row = rows %]
+ [% tr_class = loop.count % 2 ? 'report_row_even' : 'report_row_odd' %]
+ <tr class="[% tr_class FILTER html %]">
+ [% FOREACH field = row %]
+ <td>[% field FILTER html %]</td>
+ [% END %]
+ </tr>
+ [% END %]
+ </table>
+ [% ELSE %]
+ <i>no results</i>
+ [% END %]
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl b/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl
new file mode 100644
index 000000000..71228014a
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl
@@ -0,0 +1,103 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Release Tracking Report"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+ javascript_urls = [ "extensions/BMO/web/js/release_tracking_report.js" ]
+%]
+
+<noscript>
+<h1>JavaScript is required to use this report.</h1>
+</noscript>
+
+<script>
+var flags_data = [% flags_json FILTER none %];
+var products_data = [% products_json FILTER none %];
+var fields_data = [% fields_json FILTER none %];
+var default_query = '[% default_query FILTER js %]';
+</script>
+
+<form action="page.cgi" method="get" onSubmit="return onFormSubmit()">
+<input type="hidden" name="id" value="release_tracking_report.html">
+<input type="hidden" name="q" id="q" value="">
+<table>
+
+<tr>
+ <th>Approval:</th>
+ <td>
+ Show [% terms.bugs %] where
+ <select id="flag" onChange="onFlagChange()">
+ [% FOREACH flag_name = flag_names %]
+ <option value="[% flag_name FILTER html %]">[% flag_name FILTER html %]</option>
+ [% END %]
+ </select>
+
+ was changed to (and is currently)
+ <select id="flag_value">
+ <option value="?">?</option>
+ <option value="-">-</option>
+ <option value="+">+</option>
+ </select>
+
+ between
+ <select id="range" onChange="serialiseForm()">
+ [% FOREACH range = ranges %]
+ <option value="[% range.value FILTER html %]">
+ [% range.label FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <th>Status:</th>
+ <td>
+ for the product
+ <select id="product" onChange="onProductChange()">
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <select id="op" onChange="serialiseForm()">
+ <option value="and">All selected tracking fields (AND)</option>
+ <option value="or">Any selected tracking fields (OR)</option>
+ </select>
+ [
+ <a href="javascript:void(0)" onClick="selectAllFields()">All</a> |
+ <a href="javascript:void(0)" onClick="selectNoFields()">None</a>
+ ]
+ [
+ <a href="javascript:void(0)" onClick="invertFields()">Invert</a>
+ ]
+ <br>
+ <span id="tracking_span">
+ </span>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td colspan="2">
+ <input type="submit" value="Search">
+ <input type="submit" value="Reset" onClick="onFormReset(); return false">
+ <a href="?" id="bookmark">Bookmarkable Link</a>
+ </td>
+</tr>
+</table>
+</form>
+
+<p>
+ <i>"fixed" in the status field checks for the "verified" status as well as "fixed".</i>
+</p>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/researchers.html.tmpl b/extensions/BMO/template/en/default/pages/researchers.html.tmpl
new file mode 100644
index 000000000..5f63bae62
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/researchers.html.tmpl
@@ -0,0 +1,21 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% INCLUDE global/header.html.tmpl
+ title = "$terms.Bugzilla Data For Researchers"
+%]
+
+<h2>[% terms.Bugzilla %] Data For Researchers</h2>
+
+<p>Sanitized dumps of the contents of [% terms.Bugzilla %] (with protected classes of [% terms.bugs %] including,<br>
+ but not limited to, security, legal and HR removed) are available to interested researchers.<br>
+ Please contact Mike Hoye - <a href="mailto:mhoye@mozilla.com">mhoye@mozilla.com</a>
+ - for information.</p>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl
new file mode 100644
index 000000000..a7f26e86d
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl
@@ -0,0 +1,199 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the BMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <bjones@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% js_data = BLOCK %]
+var useclassification = false;
+var first_load = true;
+var last_sel = [];
+var cpts = new Array();
+[% n = 1 %]
+[% FOREACH p = user.get_selectable_products %]
+ cpts['[% n FILTER js %]'] = [
+ [%- FOREACH c = p.components %]'[% c.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
+ [% n = n+1 %]
+[% END %]
+
+var selected_components = [
+ [%- FOREACH c = input.component %]'[% c FILTER js %]'
+ [%- ',' UNLESS loop.last %] [%- END ~%] ];
+
+[% END %]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Triage Reports"
+ yui = [ 'autocomplete', 'calendar' ]
+ javascript = js_data
+ javascript_urls = [ "js/util.js", "js/field.js", "js/productform.js",
+ "extensions/BMO/web/js/triage_reports.js" ]
+ style_urls = [ "skins/standard/buglist.css",
+ "extensions/BMO/web/styles/triage_reports.css" ]
+%]
+
+<noscript>
+<h2>Javascript is required to use this report.</h2>
+</noscript>
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+<form id="activity_form" name="activity_form" action="page.cgi" method="get"
+ onSubmit="return onGenerateReport()">
+<input type="hidden" name="id" value="triage_reports.html">
+<input type="hidden" name="action" value="run">
+
+Show UNCONFIRMED [% terms.bugs %] with:
+<table id="triage_form">
+
+<tr>
+ <th>Product:</th>
+ <td>
+ <select name="product" id="product" onChange="onSelectProduct()">
+ <option value=""></option>
+ [% FOREACH p = user.get_selectable_products %]
+ <option value="[% p.name FILTER html %]"
+ [% " selected" IF input.product == p.name %]>
+ [% p.name FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+ <td rowspan="2" valign="top">
+ <b>Comment:</b><br>
+
+ <input type="checkbox" name="filter_commenter" id="filter_commenter" value="1"
+ [% 'checked' IF input.filter_commenter %]>
+ <label for="filter_commenter">where the last commenter</label>
+ <select name="commenter" id="commenter" onChange="onCommenterChange()">
+ <option value="reporter" [% 'selected' IF input.commenter == 'reporter' %]>is the reporter</option>
+ <option value="noconfirm" [% 'selected' IF input.commenter == 'noconfirm' %]>does not have canconfirm</option>
+ <option value="is" [% 'selected' IF input.commenter == 'is' %]>is</option>
+ </select>
+ [%+ INCLUDE global/userselect.html.tmpl
+ id => "commenter_is"
+ name => "commenter_is"
+ value => input.commenter_is
+ size => 20
+ emptyok => 0
+ classes = input.commenter == "is" ? "" : "hidden"
+ %]
+ <br>
+
+ <input type="checkbox" name="filter_last" id="filter_last" value="1"
+ [% 'checked' IF input.filter_last %]>
+ <label for="filter_last">where the last comment is older than</label>
+ <select name="last" id="last" onChange="onLastChange()">
+ <option value="30" [% 'selected' IF input.last == '30' %]>30 days</option>
+ <option value="60" [% 'selected' IF input.last == '60' %]>60 days</option>
+ <option value="90" [% 'selected' IF input.last == '90' %]>90 days</option>
+ <option value="365" [% 'selected' IF input.last == '365' %]>one year</option>
+ <option value="is" [% 'selected' IF input.last == 'is' %]>the date</option>
+ </select>
+ <span id="last_is_span" class="[% 'hidden' IF input.last != 'is' %]">
+ <input type="text" id="last_is" name="last_is" size="11" maxlength="10"
+ value="[% input.last_is FILTER html %]"
+ onChange="updateCalendarLastIs(this)">
+ <button type="button" class="calendar_button" id="button_calendar_last_is"
+ onClick="showCalendar('last_is')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_last_is"></div>
+ </span>
+ <br>
+ </td>
+</tr>
+
+<tr>
+ <th>Component:</th>
+ <td>
+ <select name="component" id="component" multiple size="5">
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" value="Generate Report">
+ </td>
+</tr>
+
+</table>
+
+</form>
+<script>
+ createCalendar('last_is');
+</script>
+
+[% IF input.action == 'run' %]
+<hr>
+[% IF bugs.size > 0 %]
+ <p>
+ Found [% bugs.size %] [%+ terms.bug %][% 's' IF bugs.size != 1 %]:
+ </p>
+ <table border="0" cellspacing="0" id="report" width="100%">
+ <tr id="report-header">
+ <th>[% terms.Bug %] / Date</th>
+ <th>Summary</th>
+ <th>Reporter / Commenter</th>
+ <th>Comment Date</th>
+ <th>Last Comment</th>
+ </tr>
+
+ [% FOREACH bug = bugs %]
+ [% count = loop.count() %]
+ <tr class="bz_bugitem [% count % 2 == 1 ? "bz_row_odd" : "bz_row_even" %]">
+ <td>
+ [% bug.id FILTER bug_link(bug.id) FILTER none %]<br>
+ [% bug.creation_ts.replace(' .*' '') FILTER html FILTER no_break %]
+ </td>
+ <td>
+ [% bug.summary FILTER html %]
+ </td>
+ <td>
+ [% INCLUDE global/user.html.tmpl who = bug.reporter %]
+ [% IF bug.commenter.id != bug.reporter.id %]
+ <br>[% INCLUDE global/user.html.tmpl who = bug.commenter %]
+ [% END %]
+ </td>
+ <td>
+ [% bug.comment_ts FILTER html FILTER no_break %]
+ </td>
+ <td>
+ [% bug.comment FILTER html %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+ <p>
+ <a href="buglist.cgi?bug_id=
+ [%- FOREACH bug = bugs %][% bug.id FILTER uri %],[% END -%]
+ ">Show as a [% terms.Bug %] List</a>
+ </p>
+
+[% ELSE %]
+ <p>
+ No [% terms.bugs %] found.
+ </p>
+[% END %]
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl
new file mode 100644
index 000000000..8fa944ae6
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl
@@ -0,0 +1,304 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): David Miller <justdave@bugzilla.org>
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% INCLUDE global/header.html.tmpl
+ title = "Bugzilla 3.6 Upgrade"
+%]
+[% USE date %]
+
+<p><b>Last Updated:</b> [% date.format(template.modtime, "%d-%b-%Y %H:%M %Z") %]</p>
+
+<p>On Friday, July 9, 2010, at 11:40pm PDT (0640 UTC), bugzilla.mozilla.org was
+ <a href="show_bug.cgi?id=558044">upgraded</a> to Bugzilla 3.6.1+. Please
+ <a href="enter_bug.cgi?product=mozilla.org&amp;component=Bugzilla:+Other+b.m.o+Issues&amp;blocked=bmo-regressions">file
+ any regressions</a> for tracking purposes.</p>
+
+<h3>Known Issues</h3>
+
+<p>The following is a list of issues which are known to be broken or incomplete with this upgrade so far.</p>
+
+<ul>
+
+<li>The <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=577801&hide_resolved=1">stuff filed in Bugzilla</a>.</li>
+
+</ul>
+
+<h3>What's New</h3>
+
+<h4>Custom bugzilla.mozilla.org Changes</h4>
+
+<ul>
+ <li>Addition of autocomplete support for all user-related fields (assignee,
+ QA contact, and CC list) and the keywords field.</li>
+ <li>New attachment details UI.</li>
+ <li>New icons for the front page.</li>
+ <li>Removal of unused "Patches" column from buglist.</li>
+ <li>Initial support for <a href="http://en.wikipedia.org/wiki/Strict_Transport_Security">Strict-Transport-Security</a> (STS) header.</li>
+</ul>
+
+<h4>General Usability Improvements</h4>
+
+<p>A <a href="https://wiki.mozilla.org/Bugzilla:CMU_HCI_Research_2008">scientific
+ usability study</a> was done on [% terms.Bugzilla %] by researchers
+ from Carnegie-Mellon University. As a result of this study,
+ <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=490786&amp;hide_resolved=0">several
+ usability issues</a> were prioritized to be fixed, based on specific data
+ from the study.</p>
+
+<p>As a result, you will see many small improvements in [% terms.Bugzilla %]'s
+ usability, such as using Javascript to validate certain forms before
+ they are submitted, standardizing the words that we use in the user interface,
+ being clearer about what [% terms.Bugzilla %] needs from the user,
+ and other changes, all of which are also listed individually in this New
+ Features section.</p>
+
+<p>Work continues on improving usability for the next release of
+ [%+ terms.Bugzilla %], but the results of the research have already
+ had an impact on this 3.6 release.</p>
+
+<h4>Improved Quicksearch</h4>
+
+<p>The "quicksearch" box that appears on the front page of
+ [%+ terms.Bugzilla %] and in the header/footer of every page
+ is now simplified and made more powerful. There is a
+ <kbd>[?]</kbd> link next to the box that will take you to
+ the simplified <a href="page.cgi?id=quicksearch.html">Quicksearch Help</a>,
+ which describes every single feature of the system in a simple layout,
+ including new features such as the ability to use partial field names
+ when searching.</p>
+
+<p>Quicksearch should also be much faster than it was before, particularly
+ on large installations.</p>
+
+<p>Note that in order to implement the new quicksearch, certain old
+ and rarely-used features had to be removed:
+
+<ul>
+ <li><b>+</b> as a prefix to mean "search additional resolutions", and
+ <b>+</b> as a prefix to mean "search just the summary". You can
+ instead use <kbd>summary:</kbd> to explicitly search summaries.</li>
+ <li>Searching the Severity field if you type something that matches
+ the first few characters of a severity. You can explicitly search
+ the Severity field if you want to find [% terms.bugs %] by severity.</li>
+ <li>Searching the Priority field if you typed something that exactly
+ matched the name of a priority. You can explicitly search the
+ Priority field if you want to find [% terms.bugs %] by priority.</li>
+ <li>Searching the Platform and OS fields if you typed in one of a
+ certain hard-coded list of strings (like "pc", "windows", etc.).
+ You can explicitly search these fields, instead, if you want to
+ find [% terms.bugs %] with a specific Platform or OS set.</li>
+</ul>
+
+<h4>Simple "Browse" Interface</h4>
+
+<p>There is now a "Browse" link in the header of each [% terms.Bugzilla %]
+ page that presents a very basic interface that allows users to simply
+ browse through all open [% terms.bugs %] in particular components.</p>
+
+<h4>JSON-RPC Interface</h4>
+
+<p>[% terms.Bugzilla %] now has support for the
+ <a href="http://json-rpc.org/">JSON-RPC</a> WebServices protocol via
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Server/JSONRPC.html">jsonrpc.cgi</a>.
+ The JSON-RPC interface is experimental in this release--if you want any
+ fundamental changes in how it works,
+ <a href="http://www.bugzilla.org/developers/reporting_bugs.html">let us
+ know</a>, for the next release of [% terms.Bugzilla %].</p>
+
+<h3>New Features</h3>
+
+<h4>Enhancements for Users</h4>
+
+<ul>
+ <li><b>[% terms.Bug %] Filing:</b> When filing [% terms.abug %],
+ [%+ terms.Bugzilla %] now visually indicates which fields are
+ mandatory.</li>
+ <li><b>[% terms.Bug %] Filing:</b> "Bookmarkable templates" now
+ support the "alias" and "estimated hours" fields.</li>
+
+ <li><b>[% terms.Bug %] Editing:</b> In previous versions of
+ [%+ terms.Bugzilla %], if you added a private comment to [% terms.abug %],
+ then <em>none</em> of the changes that you made at that time were
+ sent to users who couldn't see the private comment. Now, for users
+ who can't see private comments, public changes are sent, but the private
+ comment is excluded from their email notification.</li>
+ <li><b>[% terms.Bug %] Editing:</b> The controls for groups now
+ appear to the right of the attachment and time-tracking tables,
+ when editing [% terms.abug %].</li>
+ <li><b>[% terms.Bug %] Editing:</b> The "Collapse All Comments"
+ and "Expand All Comments" links now appear to the right of the
+ comment list instead of above it.</li>
+ <li><b>[% terms.Bug %] Editing:</b> The See Also field now supports
+ URLs for Google Code Issues and the Debian B[% %]ug-Tracking System.</li>
+ <li><b>[% terms.Bug %] Editing:</b> There have been significant performance
+ improvements in <kbd>show_bug.cgi</kbd> (the script that displays the
+ [% terms.bug %]-editing form), particularly for [% terms.bugs %] that
+ have lots of comments or attachments.</li>
+
+ <li><b>Attachments:</b> The "Details" page of an attachment
+ now displays itself as uneditable if you can't edit the fields
+ there.</li>
+ <li><b>Attachments:</b> We now make sure that there is
+ a Description specified for an attachment, using JavaScript, before
+ the form is submitted.</li>
+ <li><b>Attachments:</b> There is now a link back to the [% terms.bug %]
+ at the bottom of the "Details" page for an attachment.</li>
+ <li><b>Attachments:</b> When you click on an "attachment 12345" link
+ in a comment, if the attachment is a patch, you will now see the
+ formatted "Diff" view instead of the raw patch.</li>
+ <li><b>Attachments</b>: For text attachments, we now let the browser
+ auto-detect the character encoding, instead of forcing the browser to
+ always assume the attachment is in UTF-8.</li>
+
+ <li><b>Search:</b> You can now display [% terms.bug %] flags as a column
+ in search results.</li>
+ <li><b>Search:</b> When viewing search results, you can see which columns are
+ being sorted on, and which direction the sort is on, as indicated
+ by arrows next to the column headers.</li>
+ <li><b>Search:</b> You can now search the Deadline field using relative
+ dates (like "1d", "2w", etc.).</li>
+ <li><b>Search:</b> The iCalendar format of search results now includes
+ a PRIORITY field.</li>
+ <li><b>Search:</b> It is no longer an error to enter an invalid search
+ order in a search URL--[% terms.Bugzilla %] will simply warn you that
+ some of your order options are invalid.</li>
+ <li><b>Search:</b> When there are no search results, some helpful
+ links are displayed, offering actions you might want to take.</li>
+ <li><b>Search:</b> For those who like to make their own
+ <kbd>buglist.cgi</kbd> URLs (and for people working on customizations),
+ <kbd>buglist.cgi</kbd> now accepts nearly every valid field in
+ [%+ terms.Bugzilla %] as a direct URL parameter, like
+ <kbd>&amp;field=value</kbd>.</li>
+
+ <li><b>Requests:</b> When viewing the "My Requests" page, you can now
+ see the lists as a normal search result by clicking a link at the
+ bottom of each table.</li>
+ <li><b>Requests:</b> When viewing the "My Requests" page, if you are
+ using Classifications, the Product drop-down will be grouped by
+ Classification.</li>
+
+ <li>If there are multiple languages available for your
+ [%+ terms.Bugzilla %], you can now select what language you want
+ [%+ terms.Bugzilla %] displayed in using links at the top of every
+ page.</li>
+ <li>When creating a new account, you will be automatically logged in
+ after setting your password.</li>
+ <li>There is no longer a maximum password length for accounts.</li>
+ <li>In the Dusk skin, it's now easier to see links.</li>
+ <li>In the Whining system, you can now choose to receive emails even
+ if there are no [% terms.bugs %] that match your searches.</li>
+ <li>The arrows in dependency graphs now point the other way, so that
+ [%+ terms.bugs %] point at their dependencies.</li>
+
+ <li><b>New Charts:</b> You can now convert an existing Saved Search
+ into a data series for New Charts.</li>
+ <li><b>New Charts:</b> There is now an interface that allows you to
+ delete data series.</li>
+ <li><b>New Charts:</b> When deleting a product, you now have the option
+ to delete the data series that are associated with that product.</li>
+</ul>
+
+<h4>Enhancements for Administrators and Developers</h4>
+
+<ul>
+ <li>Depending on how your workflow is set up, it is now possible to
+ have both UNCONFIRMED and REOPENED show up as status choices for
+ a closed [% terms.bug %]. If you only want one or the other to
+ show up, you should edit your status workflow appropriately
+ (possibly by removing or disabling the REOPENED status).</li>
+ <li>You can now "disable" field values so that they don't show
+ up as choices on [% terms.abug %] unless they are already set as
+ the value for that [% terms.bug %]. This doesn't work for the
+ per-product field values (component, target_milestone, and version)
+ yet, though.</li>
+ <li>Users are now locked out of their accounts for 30 minutes after
+ trying five bad passwords in a row during login. Every time a
+ user is locked out like this, the user in the "maintainer" parameter
+ will get an email.</li>
+ <li>The minimum length allowed for a password is now 6 characters.</li>
+ <li>The <kbd>UNCONFIRMED</kbd> status being enabled in a product
+ is now unrelated to the voting parameters. Instead, there is a checkbox
+ to enable the <kbd>UNCONFIRMED</kbd> status in a product.</li>
+ <li>Information about duplicates is now stored in the database instead
+ of being stored in the <kbd>data/</kbd> directory. On large installations
+ this could save several hundred megabytes of disk space.</li>
+
+ <li>When editing a group, you can now specify that members of a group
+ are allowed to grant others membership in that group itself.</li>
+ <li>The ability to compress BMP attachments to PNGs is now an Extension.
+ To enable the feature, remove the file
+ <kbd>extensions/BmpConvert/disabled</kbd> and then run checksetup.pl.</li>
+ <li>The default list of values for the Priority field are now clear English
+ words instead of P1, P2, etc.</li>
+ <li><kbd>config.cgi</kbd> now returns an ETag header and understands
+ the If-None-Match header in HTTP requests.</li>
+ <li>The XML format of <kbd>show_bug.cgi</kbd> now returns more information:
+ the numeric id of each comment, whether an attachment is a URL,
+ the modification time of an attachment, the numeric id of a flag,
+ and the numeric id of a flag's type.</li>
+</ul>
+
+<h4>WebService Changes</h4>
+
+<ul>
+ <li>The WebService now returns all dates and times in the UTC timezone.
+ <kbd>B[% %]ugzilla.time</kbd> now acts as though the [% terms.Bugzilla %]
+ server were in the UTC timezone, always. If you want to write clients
+ that are compatible across all [% terms.Bugzilla %] versions,
+ check the timezone from <kbd>B[% %]ugzilla.timezone</kbd> or
+ <kbd>B[% %]ugzilla.time</kbd>, and always input times in that timezone
+ and expect times to be returned in that format.</li>
+ <li>You can now log in by passing <kbd>Bugzilla_login</kbd> and
+ <kbd>Bugzilla_password</kbd> as arguments to any WebService function.
+ See the
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService.html#LOGGING_IN">Bugzilla::WebService</a>
+ documentation for details.</li>
+ <li>New Method:
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#attachments">B[% %]ug.attachments</a>
+ which allows getting information about attachments.</li>
+ <li>New Method:
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#fields">B[% %]ug.fields</a>,
+ which gets information about all the fields that [% terms.abug %] can have
+ in [% terms.Bugzilla %], include custom fields and legal values for
+ all fields. The <kbd>B[% %]ug.legal_values</kbd> method is now deprecated.</li>
+ <li>In the <kbd>B[% %]ug.add_comment</kbd> method, the "private" parameter
+ has been renamed to "is_private" (for consistency with other methods).
+ You can still use "private", though, for backwards-compatibility.</li>
+ <li>The WebService now has Perl's "taint mode" turned on. This means that
+ it validates all data passed in before sending it to the database.
+ Also, all parameter names are validated, and if you pass in a parameter
+ whose name contains anything other than letters, numbers, or underscores,
+ that parameter will be ignored. Mostly this just affects
+ customizers--[% terms.Bugzilla %]'s WebService is not functionally
+ affected by these changes.</li>
+ <li>In previous versions of [% terms.Bugzilla %], error messages were
+ sent word-wrapped to the client, from the WebService. Error messages
+ are now sent as one unbroken line.</li>
+</ul>
+
+<h3>Last Ten Commits</h3>
+
+<pre>[% bzr_history.join('') FILTER html %]</pre>
+
+<br>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/user_activity.html.tmpl b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl
new file mode 100644
index 000000000..f299b862b
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl
@@ -0,0 +1,226 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF who %]
+[% who_title = ' (' _ who _ ')' %]
+[% ELSE %]
+[% who_title = '' %]
+[% END %]
+
+[% INCLUDE global/header.html.tmpl
+ title = "User Activity Report" _ who_title
+ yui = [ 'autocomplete', 'calendar' ]
+ javascript_urls = [ "js/util.js", "js/field.js" ]
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+
+%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS bug/time.html.tmpl %]
+
+<form id="activity_form" name="activity_form" action="page.cgi" method="get">
+<input type="hidden" name="id" value="user_activity.html">
+<input type="hidden" name="action" value="run">
+<table id="parameters">
+
+<tr>
+ <th>
+ Who:
+ </th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "who"
+ name => "who"
+ value => who
+ size => 40
+ emptyok => 0
+ title => "One or more email address (comma delimited)"
+ %]
+ &nbsp;
+ </td>
+ <th>
+ Period:
+ </th>
+ <td>
+ <input type="text" id="from" name="from" size="11"
+ align="right" value="[% from FILTER html %]" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_from"
+ onclick="showCalendar('from')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_from"></div>
+ to
+ <input type="text" name="to" size="11" id="to"
+ align="right" value ="[% to FILTER html %]" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_to"
+ onclick="showCalendar('to')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_to"></div>
+ </td>
+ <th>
+ Sort:
+ </th>
+ <td>
+ <select name="sort">
+ <option value="when" [% 'selected' IF sort == 'when' %]>When</option>
+ <option value="bug" [% 'selected' IF sort == 'bug' %]>[% terms.Bug %]</option>
+ </select>
+ </td>
+ <td>
+ <input type="submit" id="run" value="Generate Report">
+ </td>
+</tr>
+
+</table>
+[% IF debug_sql %]
+ <input type="hidden" name="debug" value="1">
+[% END %]
+</form>
+
+<script type="text/javascript">
+ createCalendar('from');
+ createCalendar('to');
+</script>
+
+[% IF action == 'run' %]
+
+[% IF debug_sql %]
+ <pre>[% debug_sql FILTER html %]</pre>
+[% END %]
+
+[% IF incomplete_data %]
+ <p>
+ There used to be an issue in <a href="http://www.bugzilla.org/">Bugzilla</a>
+ which caused activity data to be lost if there were a large number of cc's
+ or dependencies. That has been fixed, but some data was already lost in
+ your activity table that could not be regenerated. The changes that
+ could not reliably determine are prefixed by '?'.
+ </p>
+[% END %]
+
+[% IF operations.size > 0 %]
+ <br>
+ <table border="1" cellpadding="4" cellspacing="0" id="report" class="hover">
+ <tr id="report-header">
+ [% IF who_count > 1 %]
+ <th>Who</th>
+ [% END %]
+ [% IF sort == 'when' %]
+ <th class="sorted">[% INCLUDE sort_when_link %]</th>
+ <th>[% INCLUDE sort_bug_link %]</th>
+ [% ELSE %]
+ <th class="sorted">[% INCLUDE sort_bug_link %]</th>
+ <th>[% INCLUDE sort_when_link %]</th>
+ [% END %]
+ <th>What</th>
+ <th>Removed</th>
+ <th>Added</th>
+ </tr>
+
+ [% FOREACH operation = operations %]
+ [% tr_class = loop.count % 2 ? 'report_row_even' : 'report_row_odd' %]
+ [% FOREACH change = operation.changes %]
+ <tr class="[% tr_class FILTER none %]">
+ [% IF loop.count == 1 %]
+ [% IF who_count > 1 %]
+ <td>[% operation.who FILTER email FILTER html %]</td>
+ [% END %]
+ [% IF sort == 'when' %]
+ <td>[% change.when FILTER time FILTER no_break %]</td>
+ <td>[% operation.bug FILTER bug_link(operation.bug) FILTER none %]</td>
+ [% ELSE %]
+ <td>[% operation.bug FILTER bug_link(operation.bug) FILTER none %]</td>
+ <td>[% change.when FILTER time FILTER no_break %]</td>
+ [% END %]
+ [% ELSE %]
+ [% IF who_count > 1 %]
+ <td>&nbsp;</td>
+ [% END %]
+ <td>&nbsp;</td>
+ [% IF sort == 'when' %]
+ <td>&nbsp;</td>
+ [% ELSE %]
+ <td>[% change.when FILTER time FILTER no_break %]</td>
+ [% END %]
+ [% END %]
+ <td>
+ [% IF change.attachid %]
+ <a href="attachment.cgi?id=[% change.attachid FILTER uri %]"
+ title="[% change.attach.description FILTER html %]
+ [%- %] - [% change.attach.filename FILTER html %]"
+ >Attachment #[% change.attachid FILTER html %]</a>
+ [% END %]
+ [%IF change.comment.defined && change.fieldname == 'longdesc' %]
+ [% "Comment $change.comment.count"
+ FILTER bug_link(operation.bug, comment_num => change.comment.count)
+ FILTER none %]
+ [% ELSE %]
+ [%+ field_descs.${change.fieldname} FILTER html %]
+ [% END %]
+ </td>
+ [% PROCESS change_column change_type = change.removed %]
+ [% PROCESS change_column change_type = change.added %]
+ </tr>
+ [% END %]
+ [% END %]
+ </table>
+ <p>
+ <a href="buglist.cgi?bug_id=[% bug_ids.join(',') FILTER uri %]">
+ Show as a [% terms.Bug %] List</a>
+ </p>
+
+[% ELSE %]
+ <p>
+ No changes.
+ </p>
+[% END %]
+
+[% BLOCK change_column %]
+ <td>
+ [% IF change_type.defined %]
+ [% IF change.fieldname == 'estimated_time' ||
+ change.fieldname == 'remaining_time' ||
+ change.fieldname == 'work_time' %]
+ [% PROCESS formattimeunit time_unit=change_type %]
+ [% ELSIF change.fieldname == 'blocked' ||
+ change.fieldname == 'dependson' %]
+ [% change_type FILTER bug_list_link FILTER none %]
+ [% ELSIF change.fieldname == 'assigned_to' ||
+ change.fieldname == 'reporter' ||
+ change.fieldname == 'qa_contact' ||
+ change.fieldname == 'cc' ||
+ change.fieldname == 'flagtypes.name' %]
+ [% display_value(change.fieldname, change_type) FILTER email FILTER html %]
+ [% ELSE %]
+ [% display_value(change.fieldname, change_type) FILTER html %]
+ [% END %]
+ [% ELSE %]
+ &nbsp;
+ [% END %]
+ </td>
+[% END %]
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
+
+[% BLOCK sort_when_link %]
+ <a href="page.cgi?id=user_activity.html&amp;action=run&amp;
+ [%~%]who=[% who FILTER uri %]&amp;
+ [%~%]from=[% from FILTER uri %]&amp;
+ [%~%]to=[% to FILTER uri %]&amp;
+ [%~%]sort=when">When</a>
+[% END %]
+
+[% BLOCK sort_bug_link %]
+ <a href="page.cgi?id=user_activity.html&amp;action=run&amp;
+ [%~%]who=[% who FILTER uri %]&amp;
+ [%~%]from=[% from FILTER uri %]&amp;
+ [%~%]to=[% to FILTER uri %]&amp;
+ [%~%]sort=bug">[% terms.Bug %]</a>
+[% END %]
diff --git a/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl
new file mode 100644
index 000000000..0c52c1a58
--- /dev/null
+++ b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl
@@ -0,0 +1,17 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+<ShortName>[% terms.BugzillaTitle %]</ShortName>
+<Description>[% terms.BugzillaTitle %] Quick Search</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image height="16" width="16" type="image/vnd.microsoft.icon">https://bugzilla.mozilla.org/extensions/BMO/web/images/favicon.ico</Image>
+<Url type="text/html" method="GET" template="[% urlbase FILTER xml %]buglist.cgi?quicksearch={searchTerms}"/>
+</OpenSearchDescription>
diff --git a/extensions/BMO/web/core.png b/extensions/BMO/web/core.png
new file mode 100644
index 000000000..b9c5053f6
--- /dev/null
+++ b/extensions/BMO/web/core.png
Binary files differ
diff --git a/extensions/BMO/web/images/advanced.png b/extensions/BMO/web/images/advanced.png
new file mode 100644
index 000000000..71a3fcb78
--- /dev/null
+++ b/extensions/BMO/web/images/advanced.png
Binary files differ
diff --git a/extensions/BMO/web/images/background.png b/extensions/BMO/web/images/background.png
new file mode 100644
index 000000000..eb254aab9
--- /dev/null
+++ b/extensions/BMO/web/images/background.png
Binary files differ
diff --git a/extensions/BMO/web/images/bugzilla.png b/extensions/BMO/web/images/bugzilla.png
new file mode 100644
index 000000000..4b7c10284
--- /dev/null
+++ b/extensions/BMO/web/images/bugzilla.png
Binary files differ
diff --git a/extensions/BMO/web/images/favicon.ico b/extensions/BMO/web/images/favicon.ico
new file mode 100644
index 000000000..c14fec40a
--- /dev/null
+++ b/extensions/BMO/web/images/favicon.ico
Binary files differ
diff --git a/extensions/BMO/web/images/groups/bugzilla-approvers.png b/extensions/BMO/web/images/groups/bugzilla-approvers.png
new file mode 100644
index 000000000..d2414e041
--- /dev/null
+++ b/extensions/BMO/web/images/groups/bugzilla-approvers.png
Binary files differ
diff --git a/extensions/BMO/web/images/groups/calendar-drivers.png b/extensions/BMO/web/images/groups/calendar-drivers.png
new file mode 100644
index 000000000..fc2c1d1e5
--- /dev/null
+++ b/extensions/BMO/web/images/groups/calendar-drivers.png
Binary files differ
diff --git a/extensions/BMO/web/images/guided.png b/extensions/BMO/web/images/guided.png
new file mode 100644
index 000000000..46ba060f8
--- /dev/null
+++ b/extensions/BMO/web/images/guided.png
Binary files differ
diff --git a/extensions/BMO/web/images/mozchomp.gif b/extensions/BMO/web/images/mozchomp.gif
new file mode 100644
index 000000000..ac6549527
--- /dev/null
+++ b/extensions/BMO/web/images/mozchomp.gif
Binary files differ
diff --git a/extensions/BMO/web/images/mozilla-tab.png b/extensions/BMO/web/images/mozilla-tab.png
new file mode 100644
index 000000000..417f6a5c6
--- /dev/null
+++ b/extensions/BMO/web/images/mozilla-tab.png
Binary files differ
diff --git a/extensions/BMO/web/images/presshat.png b/extensions/BMO/web/images/presshat.png
new file mode 100644
index 000000000..a61de59e5
--- /dev/null
+++ b/extensions/BMO/web/images/presshat.png
Binary files differ
diff --git a/extensions/BMO/web/images/sign_warning.png b/extensions/BMO/web/images/sign_warning.png
new file mode 100644
index 000000000..30963f47d
--- /dev/null
+++ b/extensions/BMO/web/images/sign_warning.png
Binary files differ
diff --git a/extensions/BMO/web/images/stop-sign.gif b/extensions/BMO/web/images/stop-sign.gif
new file mode 100644
index 000000000..9b420ec6c
--- /dev/null
+++ b/extensions/BMO/web/images/stop-sign.gif
Binary files differ
diff --git a/extensions/BMO/web/images/throbber.gif b/extensions/BMO/web/images/throbber.gif
new file mode 100644
index 000000000..bc4fa6561
--- /dev/null
+++ b/extensions/BMO/web/images/throbber.gif
Binary files differ
diff --git a/extensions/BMO/web/js/edit_bug.js b/extensions/BMO/web/js/edit_bug.js
new file mode 100644
index 000000000..e630eb995
--- /dev/null
+++ b/extensions/BMO/web/js/edit_bug.js
@@ -0,0 +1,91 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the BMO Bugzilla Extension;
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+// --- custom flags
+var Dom = YAHOO.util.Dom;
+
+function bmo_hide_tracking_flags() {
+ for (var field in bmo_custom_flags) {
+ var el = Dom.get(field);
+ var value = el ? el.value : bmo_custom_flags[field];
+ if (el && (value != bmo_custom_flags[field])) {
+ bmo_show_tracking_flags();
+ return;
+ }
+ if (value == '---') {
+ Dom.addClass('row_' + field, 'bz_hidden');
+ } else {
+ Dom.addClass(field, 'bz_hidden');
+ Dom.removeClass('ro_' + field, 'bz_hidden');
+ }
+ }
+}
+
+function bmo_show_tracking_flags() {
+ Dom.addClass('edit_tracking_fields_action', 'bz_hidden');
+ for (var field in bmo_custom_flags) {
+ if (Dom.get(field).value == '---') {
+ Dom.removeClass('row_' + field, 'bz_hidden');
+ } else {
+ Dom.removeClass(field, 'bz_hidden');
+ Dom.addClass('ro_' + field, 'bz_hidden');
+ }
+ }
+}
+
+function init_clone_bug_menu(el, bug_id, product, component) {
+ var diff_url = 'enter_bug.cgi?cloned_bug_id=' + bug_id;
+ var cur_url = diff_url +
+ '&product=' + encodeURIComponent(product) +
+ '&component=' + encodeURIComponent(component);
+ var menu = new YAHOO.widget.Menu('clone_bug_menu', { position : 'dynamic' });
+ menu.addItems([
+ { text: 'Clone to the current product', url: cur_url },
+ { text: 'Clone to a different product', url: diff_url }
+ ]);
+ menu.render(document.body);
+ YAHOO.util.Event.addListener(el, 'click', show_clone_bug_menu, menu);
+}
+
+function show_clone_bug_menu(event, menu) {
+ menu.cfg.setProperty('xy', YAHOO.util.Event.getXY(event));
+ menu.show();
+ event.preventDefault();
+}
+
+// -- make attachment table, comments, new comment textarea equal widths
+
+YAHOO.util.Event.onDOMReady(function() {
+ var comment_tables = Dom.getElementsByClassName('bz_comment_table', 'table', 'comments');
+ if (comment_tables.length) {
+ var comment_width = comment_tables[0].getElementsByTagName('td')[0].clientWidth + 'px';
+ var attachment_table = Dom.get('attachment_table');
+ if (attachment_table)
+ attachment_table.style.width = comment_width;
+ var new_comment = Dom.get('comment');
+ if (new_comment)
+ new_comment.style.width = comment_width;
+ }
+});
diff --git a/extensions/BMO/web/js/edituser_menu.js b/extensions/BMO/web/js/edituser_menu.js
new file mode 100644
index 000000000..4f6d6ec69
--- /dev/null
+++ b/extensions/BMO/web/js/edituser_menu.js
@@ -0,0 +1,33 @@
+var usermenu_widget;
+
+YAHOO.util.Event.onDOMReady(function() {
+ usermenu_widget = new YAHOO.widget.Menu('usermenu_widget', { position : 'dynamic' });
+ usermenu_widget.addItems([
+ { text: 'Activity', url: '#', target: '_blank' },
+ { text: 'Mail', url: '#', target: '_blank' },
+ { text: 'Edit', url: '#', target: '_blank' }
+ ]);
+ usermenu_widget.render(document.body);
+});
+
+function show_usermenu(event, id, email, show_edit) {
+ if (!usermenu_widget)
+ return true;
+ if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)
+ return true;
+ usermenu_widget.getItem(0).cfg.setProperty('url',
+ 'page.cgi?id=user_activity.html&action=run' +
+ '&from=' + YAHOO.util.Date.format(new Date(new Date() - (1000 * 60 * 60 * 24 * 14)), {format: '%Y-%m-%d'}) +
+ '&to=' + YAHOO.util.Date.format(new Date(), {format: '%Y-%m-%d'}) +
+ '&who=' + encodeURIComponent(email));
+ usermenu_widget.getItem(1).cfg.setProperty('url', 'mailto:' + encodeURIComponent(email));
+ if (show_edit) {
+ usermenu_widget.getItem(2).cfg.setProperty('url', 'editusers.cgi?action=edit&userid=' + id);
+ } else {
+ usermenu_widget.removeItem(2);
+ }
+ usermenu_widget.cfg.setProperty('xy', YAHOO.util.Event.getXY(event));
+ usermenu_widget.show();
+ return false;
+}
+
diff --git a/extensions/BMO/web/js/form_validate.js b/extensions/BMO/web/js/form_validate.js
new file mode 100644
index 000000000..6c8fa6f07
--- /dev/null
+++ b/extensions/BMO/web/js/form_validate.js
@@ -0,0 +1,21 @@
+/**
+ * Some Form Validation and Interaction
+ **/
+//Makes sure that there is an '@' in the address with a '.'
+//somewhere after it (and at least one character in between them
+
+function isValidEmail(email) {
+ var at_index = email.indexOf("@");
+ var last_dot = email.lastIndexOf(".");
+ return at_index > 0 && last_dot > (at_index + 1);
+}
+
+//Takes a DOM element id and makes sure that it is filled out
+function isFilledOut(elem_id) {
+ var str = document.getElementById(elem_id).value;
+ return str.length>0 && str!="noneselected";
+}
+
+function isChecked(elem_id) {
+ return document.getElementById(elem_id).checked;
+}
diff --git a/extensions/BMO/web/js/release_tracking_report.js b/extensions/BMO/web/js/release_tracking_report.js
new file mode 100644
index 000000000..840b57df1
--- /dev/null
+++ b/extensions/BMO/web/js/release_tracking_report.js
@@ -0,0 +1,203 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+var Dom = YAHOO.util.Dom;
+var flagEl;
+var productEl;
+var trackingEl;
+var selectedFields;
+
+// events
+
+function onFieldToggle(cbEl, id) {
+ if (cbEl.checked) {
+ Dom.removeClass('field_' + id + '_td', 'disabled');
+ selectedFields['field_' + id] = id;
+ } else {
+ Dom.addClass('field_' + id + '_td', 'disabled');
+ selectedFields['field_' + id] = false;
+ }
+ Dom.get('field_' + id + '_select').disabled = !cbEl.checked;
+ serialiseForm();
+}
+
+function onProductChange() {
+ var product = productEl.value;
+ var productData = product == '0' ? getFlagByName(flagEl.value) : getProductById(product);
+ var html = '';
+ selectedFields = new Array();
+
+ if (productData) {
+ // update status fields
+ html = '<table>';
+ for(var i = 0, l = productData.fields.length; i < l; i++) {
+ var field = getFieldById(productData.fields[i]);
+ selectedFields['field_' + field.id] = false;
+ html += '<tr>' +
+ '<td>' +
+ '<input type="checkbox" id="field_' + field.id + '_cb" ' +
+ 'onClick="onFieldToggle(this,' + field.id + ')">' +
+ '</td>' +
+ '<td class="disabled" id="field_' + field.id + '_td">' +
+ '<label for="field_' + field.id + '_cb">' +
+ YAHOO.lang.escapeHTML(field.name) + ':</label>' +
+ '</td>' +
+ '<td>' +
+ '<select disabled id="field_' + field.id + '_select">' +
+ '<option value="+">fixed</option>' +
+ '<option value="-">not fixed</option>' +
+ '</select>' +
+ '</td>' +
+ '</tr>';
+ }
+ html += '</table>';
+ }
+ trackingEl.innerHTML = html;
+ serialiseForm();
+}
+
+function onFlagChange() {
+ var flag = flagEl.value;
+ var flagData = getFlagByName(flag);
+ productEl.options.length = 0;
+
+ if (flagData) {
+ // update product select
+ var currentProduct = productEl.value;
+ productEl.options[0] = new Option('(Any Product)', '0');
+ for(var i = 0, l = flagData.products.length; i < l; i++) {
+ var product = getProductById(flagData.products[i]);
+ var n = productEl.length;
+ productEl.options[n] = new Option(product.name, product.id);
+ productEl.options[n].selected = product.id == currentProduct;
+ }
+ }
+ onProductChange();
+}
+
+// form
+
+function selectAllFields() {
+ for(var i = 0, l = fields_data.length; i < l; i++) {
+ var cb = Dom.get('field_' + fields_data[i].id + '_cb');
+ cb.checked = true;
+ onFieldToggle(cb, fields_data[i].id);
+ }
+ serialiseForm();
+}
+
+function selectNoFields() {
+ for(var i = 0, l = fields_data.length; i < l; i++) {
+ var cb = Dom.get('field_' + fields_data[i].id + '_cb');
+ cb.checked = false;
+ onFieldToggle(cb, fields_data[i].id);
+ }
+ serialiseForm();
+}
+
+function invertFields() {
+ for(var i = 0, l = fields_data.length; i < l; i++) {
+ var el = Dom.get('field_' + fields_data[i].id + '_select');
+ if (el.value == '+') {
+ el.options[1].selected = true;
+ } else {
+ el.options[0].selected = true;
+ }
+ }
+ serialiseForm();
+}
+
+function onFormSubmit() {
+ serialiseForm();
+ return true;
+}
+
+function onFormReset() {
+ deserialiseForm('');
+}
+
+function serialiseForm() {
+ var q = flagEl.value + ':' +
+ Dom.get('flag_value').value + ':' +
+ Dom.get('range').value + ':' +
+ productEl.value + ':' +
+ Dom.get('op').value + ':';
+
+ for(var id in selectedFields) {
+ if (selectedFields[id]) {
+ q += selectedFields[id] + Dom.get(id + '_select').value + ':';
+ }
+ }
+
+ Dom.get('q').value = q;
+ Dom.get('bookmark').href = 'page.cgi?id=release_tracking_report.html&q=' +
+ encodeURIComponent(q);
+}
+
+function deserialiseForm(q) {
+ var parts = q.split(/:/);
+ selectValue(flagEl, parts[0]);
+ onFlagChange();
+ selectValue(Dom.get('flag_value'), parts[1]);
+ selectValue(Dom.get('range'), parts[2]);
+ selectValue(productEl, parts[3]);
+ onProductChange();
+ selectValue(Dom.get('op'), parts[4]);
+ for(var i = 5, l = parts.length; i < l; i++) {
+ var part = parts[i];
+ if (part.length) {
+ var value = part.substr(part.length - 1, 1);
+ var id = part.substr(0, part.length - 1);
+ var cb = Dom.get('field_' + id + '_cb');
+ cb.checked = true;
+ onFieldToggle(cb, id);
+ selectValue(Dom.get('field_' + id + '_select'), value);
+ }
+ }
+ serialiseForm();
+}
+
+// utils
+
+YAHOO.util.Event.onDOMReady(function() {
+ flagEl = Dom.get('flag');
+ productEl = Dom.get('product');
+ trackingEl = Dom.get('tracking_span');
+ onFlagChange();
+ deserialiseForm(default_query);
+});
+
+function getFlagByName(name) {
+ for(var i = 0, l = flags_data.length; i < l; i++) {
+ if (flags_data[i].name == name)
+ return flags_data[i];
+ }
+}
+
+function getProductById(id) {
+ for(var i = 0, l = products_data.length; i < l; i++) {
+ if (products_data[i].id == id)
+ return products_data[i];
+ }
+}
+
+function getFieldById(id) {
+ for(var i = 0, l = fields_data.length; i < l; i++) {
+ if (fields_data[i].id == id)
+ return fields_data[i];
+ }
+}
+
+function selectValue(el, value) {
+ for(var i = 0, l = el.options.length; i < l; i++) {
+ if (el.options[i].value == value) {
+ el.options[i].selected = true;
+ return;
+ }
+ }
+ el.options[0].selected = true;
+}
diff --git a/extensions/BMO/web/js/sorttable.js b/extensions/BMO/web/js/sorttable.js
new file mode 100644
index 000000000..0873dc20a
--- /dev/null
+++ b/extensions/BMO/web/js/sorttable.js
@@ -0,0 +1,709 @@
+/*
+ SortTable
+ version 2
+ 7th April 2007
+ Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
+
+ Instructions:
+ Download this file
+ Add <script src="sorttable.js"></script> to your HTML
+ Add class="sortable" to any table you'd like to make sortable
+ Click on the headers to sort
+
+ Thanks to many, many people for contributions and suggestions.
+ Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
+ This basically means: do what you want with it.
+*/
+
+var stIsIE = /*@cc_on!@*/false;
+
+sorttable = {
+ init: function() {
+ // quit if this function has already been called
+ if (arguments.callee.done) return;
+ // flag this function so we don't do the same thing twice
+ arguments.callee.done = true;
+ // kill the timer
+ if (_timer) clearInterval(_timer);
+
+ if (!document.createElement || !document.getElementsByTagName) return;
+
+ sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
+
+ forEach(document.getElementsByTagName('table'), function(table) {
+ if (table.className.search(/\bsortable\b/) != -1) {
+ sorttable.makeSortable(table);
+ }
+ });
+
+ },
+
+ /*
+ * Prepares the table so that it can be sorted
+ *
+ */
+ makeSortable: function(table) {
+
+ if (table.getElementsByTagName('thead').length == 0) {
+ // table doesn't have a tHead. Since it should have, create one and
+ // put the first table row in it.
+ the = document.createElement('thead');
+ the.appendChild(table.rows[0]);
+ table.insertBefore(the,table.firstChild);
+ }
+ // Safari doesn't support table.tHead, sigh
+ if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
+
+ //if (table.tHead.rows.length != 1) return; // can't cope with two header rows
+
+ // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
+ // "total" rows, for example). This is B&R, since what you're supposed
+ // to do is put them in a tfoot. So, if there are sortbottom rows,
+ // for backwards compatibility, move them to tfoot (creating it if needed).
+ sortbottomrows = [];
+ for (var i=0; i<table.rows.length; i++) {
+ if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
+ sortbottomrows[sortbottomrows.length] = table.rows[i];
+ }
+ }
+
+ if (sortbottomrows) {
+ if (table.tFoot == null) {
+ // table doesn't have a tfoot. Create one.
+ tfo = document.createElement('tfoot');
+ table.appendChild(tfo);
+ }
+ for (var i=0; i<sortbottomrows.length; i++) {
+ tfo.appendChild(sortbottomrows[i]);
+ }
+ delete sortbottomrows;
+ }
+
+ sorttable._walk_through_headers(table);
+ },
+
+ /*
+ * Helper function for preparing the table
+ *
+ */
+ _walk_through_headers: function(table) {
+ // First, gather some information we need to sort the table.
+ var bodies = [];
+ var table_rows = [];
+ var body_size = table.tBodies[0].rows.length;
+
+ // We need to get all the rows
+ for (var i=0; i<table.tBodies.length; i++) {
+ if (!table.tBodies[i].className.match(/\bsorttable_body\b/))
+ continue;
+
+ bodies[bodies.length] = table.tBodies[i];
+ for (j=0; j<table.tBodies[i].rows.length; j++) {
+ table_rows[table_rows.length] = table.tBodies[i].rows[j];
+ }
+ }
+
+ table.sorttable_rows = table_rows;
+ table.sorttable_body_size = body_size;
+ table.sorttable_bodies = bodies;
+
+
+ // work through each column and calculate its type
+
+ // For each row in the header..
+ for (var row_index=0; row_index < table.tHead.rows.length; row_index++) {
+
+ headrow = table.tHead.rows[row_index].cells;
+ // ... Walk through each column and calculate the type.
+ for (var i=0; i<headrow.length; i++) {
+ // Don't sort this column, please
+ if (headrow[i].className.match(/\bsorttable_nosort\b/)) continue;
+
+ // Override sort column index.
+ column_index = i;
+ mtch = headrow[i].className.match(/\bsortable_column_([a-z0-9]+)\b/);
+ if (mtch) column_index = mtch[1];
+
+
+ // Manually override the type with a sorttable_type attribute
+ // Override sort function
+ mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
+ if (mtch) override = mtch[1];
+
+ if (mtch && typeof sorttable["sort_"+override] == 'function') {
+ headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
+ } else {
+ headrow[i].sorttable_sortfunction = sorttable.guessType(table, column_index);
+ }
+
+ // make it clickable to sort
+ headrow[i].sorttable_columnindex = column_index;
+ headrow[i].table = table;
+
+ // If the header contains a link, clear the href.
+ for (var k=0; k<headrow[i].childNodes.length; k++) {
+ if (headrow[i].childNodes[k].tagName == 'A') {
+ headrow[i].childNodes[k].href = "javascript:void(0);";
+ }
+ }
+
+ dean_addEvent(headrow[i], "click", sorttable._on_column_header_clicked);
+
+ } // inner for (var i=0; i<headrow.length; i++)
+ } // outer for
+ },
+
+
+
+
+ /*
+ * Helper function for the _on_column_header_clicked handler
+ *
+ */
+
+ _remove_sorted_classes: function(header) {
+ // For each row in the header..
+ for (var j=0; j< header.rows.length; j++) {
+ // ... Walk through each column and calculate the type.
+ row = header.rows[j].cells;
+
+ for (var i=0; i<row.length; i++) {
+ cell = row[i];
+ if (cell.nodeType != 1) return; // an element
+
+ mtch = cell.className.match(/\bsorted_([0-9]+)\b/);
+ if (mtch) {
+ cell.className = cell.className.replace('sorted_'+mtch[1],
+ 'sorted_'+(parseInt(mtch[1])+1));
+ }
+
+ cell.className = cell.className.replace('sorttable_sorted_reverse','');
+ cell.className = cell.className.replace('sorttable_sorted','');
+ }
+ }
+ },
+
+ _check_already_sorted: function(cell) {
+ if (cell.className.search(/\bsorttable_sorted\b/) != -1) {
+ // if we're already sorted by this column, just
+ // reverse the table, which is quicker
+ sorttable.reverse_table(cell);
+
+ sorttable._mark_column_as_sorted(cell, '&#x25BC;', 1);
+ return 1;
+ }
+
+ if (cell.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
+ // if we're already sorted by this column in reverse, just
+ // re-reverse the table, which is quicker
+ sorttable.reverse_table(cell);
+
+ sorttable._mark_column_as_sorted(cell, '&#x25B2;', 0);
+
+ return 1;
+ }
+
+ return 0;
+ },
+
+ /* Visualy mark the cell as sorted.
+ *
+ * @param cell: the cell being marked
+ * @param text: the text being used to mark. you can use html
+ * @param reversed: whether the column is reversed or not.
+ *
+ */
+ _mark_column_as_sorted: function(cell, text, reversed) {
+ // remove eventual class
+ cell.className = cell.className.replace('sorttable_sorted', '');
+ cell.className = cell.className.replace('sorttable_sorted_reverse', '');
+
+ // the column is reversed
+ if (reversed) {
+ cell.className += ' sorttable_sorted_reverse';
+ }
+ else {
+ // remove eventual class
+ cell.className += ' sorttable_sorted';
+ }
+
+ sorttable._remove_sorting_marker();
+
+ marker = document.createElement('span');
+ marker.id = "sorttable_sort_mark";
+ marker.className = "bz_sort_order_primary";
+ marker.innerHTML = text;
+ cell.appendChild(marker);
+ },
+
+ _remove_sorting_marker: function() {
+ mark = document.getElementById('sorttable_sort_mark');
+ if (mark) { mark.parentNode.removeChild(mark); }
+ els = sorttable._getElementsByClassName('bz_sort_order_primary');
+ for(var i=0,j=els.length; i<j; i++) {
+ els[i].parentNode.removeChild(els[i]);
+ }
+ els = sorttable._getElementsByClassName('bz_sort_order_secondary');
+ for(var i=0,j=els.length; i<j; i++) {
+ els[i].parentNode.removeChild(els[i]);
+ }
+ },
+
+ _getElementsByClassName: function(classname, node) {
+ if(!node) node = document.getElementsByTagName("body")[0];
+ var a = [];
+ var re = new RegExp('\\b' + classname + '\\b');
+ var els = node.getElementsByTagName("*");
+ for(var i=0,j=els.length; i<j; i++)
+ if(re.test(els[i].className))a.push(els[i]);
+ return a;
+ },
+
+ /*
+ * This is the callback for when the table header is clicked.
+ *
+ * @param evt: the event that triggered this callback
+ */
+ _on_column_header_clicked: function(evt) {
+
+ // The table is already sorted by this column. Just reverse it.
+ if (sorttable._check_already_sorted(this))
+ return;
+
+
+ // First, remove sorttable_sorted classes from the other header
+ // that is currently sorted and its marker (the simbol indicating
+ // that its sorted.
+ sorttable._remove_sorted_classes(this.table.tHead);
+ mtch = this.className.match(/\bsorted_([0-9]+)\b/);
+ if (mtch) {
+ this.className = this.className.replace('sorted_'+mtch[1], '');
+ }
+ this.className += ' sorted_0 ';
+
+ // This is the text that indicates that the column is sorted.
+ sorttable._mark_column_as_sorted(this, '&#x25BC;', 0);
+
+ sorttable.sort_table(this);
+
+ },
+
+ sort_table: function(cell) {
+ // build an array to sort. This is a Schwartzian transform thing,
+ // i.e., we "decorate" each row with the actual sort key,
+ // sort based on the sort keys, and then put the rows back in order
+ // which is a lot faster because you only do getInnerText once per row
+ col = cell.sorttable_columnindex;
+ rows = cell.table.sorttable_rows;
+
+ var BUGLIST = '';
+
+ for (var j = 0; j < cell.table.sorttable_rows.length; j++) {
+ rows[j].sort_data = sorttable.getInnerText(rows[j].cells[col]);
+ }
+
+ /* If you want a stable sort, uncomment the following line */
+ sorttable.shaker_sort(rows, cell.sorttable_sortfunction);
+ /* and comment out this one */
+ //rows.sort(cell.sorttable_sortfunction);
+
+ // Rebuild the table, using he sorted rows.
+ tb = cell.table.sorttable_bodies[0];
+ body_size = cell.table.sorttable_body_size;
+ body_index = 0;
+
+ for (var j=0; j<rows.length; j++) {
+ if (j % 2)
+ rows[j].className = rows[j].className.replace('bz_row_even',
+ 'bz_row_odd');
+ else
+ rows[j].className = rows[j].className.replace('bz_row_odd',
+ 'bz_row_even');
+
+ tb.appendChild(rows[j]);
+ var bug_id = sorttable.getInnerText(rows[j].cells[0].childNodes[1]);
+ BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id;
+
+ if (j % body_size == body_size-1) {
+ body_index++;
+ if (body_index < cell.table.sorttable_bodies.length) {
+ tb = cell.table.sorttable_bodies[body_index];
+ }
+ }
+ }
+
+ document.cookie = 'BUGLIST='+BUGLIST;
+
+ cell.table.sorttable_rows = rows;
+ },
+
+ reverse_table: function(cell) {
+ oldrows = cell.table.sorttable_rows;
+ newrows = [];
+
+ for (var i=0; i < oldrows.length; i++) {
+ newrows[newrows.length] = oldrows[i];
+ }
+
+ tb = cell.table.sorttable_bodies[0];
+ body_size = cell.table.sorttable_body_size;
+ body_index = 0;
+
+ var BUGLIST = '';
+
+ cell.table.sorttable_rows = [];
+ for (var i = newrows.length-1; i >= 0; i--) {
+ if (i % 2)
+ newrows[i].className = newrows[i].className.replace('bz_row_even',
+ 'bz_row_odd');
+ else
+ newrows[i].className = newrows[i].className.replace('bz_row_odd',
+ 'bz_row_even');
+
+ tb.appendChild(newrows[i]);
+ cell.table.sorttable_rows.push(newrows[i]);
+
+ var bug_id = sorttable.getInnerText(newrows[i].cells[0].childNodes[1]);
+ BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id;
+
+ if ((newrows.length-1-i) % body_size == body_size-1) {
+ body_index++;
+ if (body_index < cell.table.sorttable_bodies.length) {
+ tb = cell.table.sorttable_bodies[body_index];
+ }
+ }
+
+ }
+
+ document.cookie = 'BUGLIST='+BUGLIST;
+
+ delete newrows;
+ },
+
+ guessType: function(table, column) {
+ // guess the type of a column based on its first non-blank row
+ sortfn = sorttable.sort_alpha;
+ for (var i=0; i<table.sorttable_bodies[0].rows.length; i++) {
+ text = sorttable.getInnerText(table.sorttable_bodies[0].rows[i].cells[column]);
+ if (text != '') {
+ if (text.match(/^-?[$]?[\d,.]+%?$/)) {
+ return sorttable.sort_numeric;
+ }
+ // check for a date: dd/mm/yyyy or dd/mm/yy
+ // can have / or . or - as separator
+ // can be mm/dd as well
+ possdate = text.match(sorttable.DATE_RE)
+ if (possdate) {
+ // looks like a date
+ first = parseInt(possdate[1]);
+ second = parseInt(possdate[2]);
+ if (first > 12) {
+ // definitely dd/mm
+ return sorttable.sort_ddmm;
+ } else if (second > 12) {
+ return sorttable.sort_mmdd;
+ } else {
+ // looks like a date, but we can't tell which, so assume
+ // that it's dd/mm (English imperialism!) and keep looking
+ sortfn = sorttable.sort_ddmm;
+ }
+ }
+ }
+ }
+ return sortfn;
+ },
+
+ getInnerText: function(node) {
+ // gets the text we want to use for sorting for a cell.
+ // strips leading and trailing whitespace.
+ // this is *not* a generic getInnerText function; it's special to sorttable.
+ // for example, you can override the cell text with a customkey attribute.
+ // it also gets .value for <input> fields.
+
+ hasInputs = (typeof node.getElementsByTagName == 'function') &&
+ node.getElementsByTagName('input').length;
+
+ if (typeof node.getAttribute != 'undefined' && node.getAttribute("sorttable_customkey") != null) {
+ return node.getAttribute("sorttable_customkey");
+ }
+ else if (typeof node.textContent != 'undefined' && !hasInputs) {
+ return node.textContent.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.innerText != 'undefined' && !hasInputs) {
+ return node.innerText.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.text != 'undefined' && !hasInputs) {
+ return node.text.replace(/^\s+|\s+$/g, '');
+ }
+ else {
+ switch (node.nodeType) {
+ case 3:
+ if (node.nodeName.toLowerCase() == 'input') {
+ return node.value.replace(/^\s+|\s+$/g, '');
+ }
+ case 4:
+ return node.nodeValue.replace(/^\s+|\s+$/g, '');
+ break;
+ case 1:
+ case 11:
+ var innerText = '';
+ for (var i = 0; i < node.childNodes.length; i++) {
+ innerText += sorttable.getInnerText(node.childNodes[i]);
+ }
+ return innerText.replace(/^\s+|\s+$/g, '');
+ break;
+ default:
+ return '';
+ }
+ }
+ },
+
+ /* sort functions
+ each sort function takes two parameters, a and b
+ you are comparing a.sort_data and b.sort_data */
+ sort_numeric: function(a,b) {
+ aa = parseFloat(a.sort_data.replace(/[^0-9.-]/g,''));
+ if (isNaN(aa)) aa = 0;
+ bb = parseFloat(b.sort_data.replace(/[^0-9.-]/g,''));
+ if (isNaN(bb)) bb = 0;
+ return aa-bb;
+ },
+
+ sort_alpha: function(a,b) {
+ if (a.sort_data.toLowerCase()==b.sort_data.toLowerCase()) return 0;
+ if (a.sort_data.toLowerCase()<b.sort_data.toLowerCase()) return -1;
+ return 1;
+ },
+
+ sort_ddmm: function(a,b) {
+ mtch = a.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ sort_mmdd: function(a,b) {
+ mtch = a.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ shaker_sort: function(list, comp_func) {
+ // A stable sort function to allow multi-level sorting of data
+ // see: http://en.wikipedia.org/wiki/Cocktail_sort
+ // thanks to Joseph Nahmias
+ var b = 0;
+ var t = list.length - 1;
+ var swap = true;
+
+ while(swap) {
+ swap = false;
+ for(var i = b; i < t; ++i) {
+ if ( comp_func(list[i], list[i+1]) > 0 ) {
+ var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
+ swap = true;
+ }
+ } // for
+ t--;
+
+ if (!swap) break;
+
+ for(var i = t; i > b; --i) {
+ if ( comp_func(list[i], list[i-1]) < 0 ) {
+ var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
+ swap = true;
+ }
+ } // for
+ b++;
+
+ } // while(swap)
+ }
+}
+
+/* ******************************************************************
+ Supporting functions: bundled here to avoid depending on a library
+ ****************************************************************** */
+
+// Dean Edwards/Matthias Miller/John Resig
+
+/* for Mozilla/Opera9 */
+if (document.addEventListener) {
+ document.addEventListener("DOMContentLoaded", sorttable.init, false);
+}
+
+/* for Internet Explorer */
+/*@cc_on @*/
+/*@if (@_win32)
+ // IE doesn't have a way to test if the DOM is loaded
+ // doing a deferred script load with onReadyStateChange checks is
+ // problematic, so poll the document until it is scrollable
+ // http://blogs.atlassian.com/developer/2008/03/when_ie_says_dom_is_ready_but.html
+ var loadTestTimer = function() {
+ try {
+ if (document.readyState != "loaded" && document.readyState != "complete") {
+ document.documentElement.doScroll("left");
+ }
+ sorttable.init(); // call the onload handler
+ } catch(error) {
+ setTimeout(loadTestTimer, 100);
+ }
+ };
+ loadTestTimer();
+/*@end @*/
+
+/* for Safari */
+if (/WebKit/i.test(navigator.userAgent)) { // sniff
+ var _timer = setInterval(function() {
+ if (/loaded|complete/.test(document.readyState)) {
+ sorttable.init(); // call the onload handler
+ }
+ }, 10);
+}
+
+/* for other browsers */
+window.onload = sorttable.init;
+
+// written by Dean Edwards, 2005
+// with input from Tino Zijdel, Matthias Miller, Diego Perini
+
+// http://dean.edwards.name/weblog/2005/10/add-event/
+
+function dean_addEvent(element, type, handler) {
+ if (element.addEventListener) {
+ element.addEventListener(type, handler, false);
+ } else {
+ // assign each event handler a unique ID
+ if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
+ // create a hash table of event types for the element
+ if (!element.events) element.events = {};
+ // create a hash table of event handlers for each element/event pair
+ var handlers = element.events[type];
+ if (!handlers) {
+ handlers = element.events[type] = {};
+ // store the existing event handler (if there is one)
+ if (element["on" + type]) {
+ handlers[0] = element["on" + type];
+ }
+ }
+ // store the event handler in the hash table
+ handlers[handler.$$guid] = handler;
+ // assign a global event handler to do all the work
+ element["on" + type] = handleEvent;
+ }
+};
+// a counter used to create unique IDs
+dean_addEvent.guid = 1;
+
+function removeEvent(element, type, handler) {
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else {
+ // delete the event handler from the hash table
+ if (element.events && element.events[type]) {
+ delete element.events[type][handler.$$guid];
+ }
+ }
+};
+
+function handleEvent(event) {
+ var returnValue = true;
+ // grab the event object (IE uses a global event object)
+ event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
+ // get a reference to the hash table of event handlers
+ var handlers = this.events[event.type];
+ // execute each event handler
+ for (var i in handlers) {
+ this.$$handleEvent = handlers[i];
+ if (this.$$handleEvent(event) === false) {
+ returnValue = false;
+ }
+ }
+ return returnValue;
+};
+
+function fixEvent(event) {
+ // add W3C standard event methods
+ event.preventDefault = fixEvent.preventDefault;
+ event.stopPropagation = fixEvent.stopPropagation;
+ return event;
+};
+fixEvent.preventDefault = function() {
+ this.returnValue = false;
+};
+fixEvent.stopPropagation = function() {
+ this.cancelBubble = true;
+}
+
+// Dean's forEach: http://dean.edwards.name/base/forEach.js
+/*
+ forEach, version 1.0
+ Copyright 2006, Dean Edwards
+ License: http://www.opensource.org/licenses/mit-license.php
+*/
+
+// array-like enumeration
+if (!Array.forEach) { // mozilla already supports this
+ Array.forEach = function(array, block, context) {
+ for (var i = 0; i < array.length; i++) {
+ block.call(context, array[i], i, array);
+ }
+ };
+}
+
+// generic enumeration
+Function.prototype.forEach = function(object, block, context) {
+ for (var key in object) {
+ if (typeof this.prototype[key] == "undefined") {
+ block.call(context, object[key], key, object);
+ }
+ }
+};
+
+// character enumeration
+String.forEach = function(string, block, context) {
+ Array.forEach(string.split(""), function(chr, index) {
+ block.call(context, chr, index, string);
+ });
+};
+
+// globally resolve forEach enumeration
+var forEach = function(object, block, context) {
+ if (object) {
+ var resolve = Object; // default
+ if (object instanceof Function) {
+ // functions have a "length" property
+ resolve = Function;
+ } else if (object.forEach instanceof Function) {
+ // the object implements a custom forEach method so use that
+ object.forEach(block, context);
+ return;
+ } else if (typeof object == "string") {
+ // the object is a string
+ resolve = String;
+ } else if (typeof object.length == "number") {
+ // the object is array-like
+ resolve = Array;
+ }
+ resolve.forEach(object, block, context);
+ }
+};
+
diff --git a/extensions/BMO/web/js/swag.js b/extensions/BMO/web/js/swag.js
new file mode 100644
index 000000000..cd9561b54
--- /dev/null
+++ b/extensions/BMO/web/js/swag.js
@@ -0,0 +1,60 @@
+/**
+ * Swag Request Form Functions
+ * Form Interal Swag Request Form
+ * dtran
+ * 7/6/09
+ **/
+
+
+function evalToNumber(numberString) {
+ if(numberString=='') return 0;
+ return parseInt(numberString);
+}
+
+function evalToNumberString(numberString) {
+ if(numberString=='') return '0';
+ return numberString;
+}
+//item_array should be an array of DOM element ids
+function getTotal(item_array) {
+ var total = 0;
+ for(var i in item_array) {
+ total += evalToNumber(document.getElementById(item_array[i]).value);
+ }
+ return total;
+}
+
+function calculateTotalSwag() {
+ document.getElementById('Totalswag').value =
+ getTotal( new Array('Lanyards',
+ 'Stickers',
+ 'Bracelets',
+ 'Tattoos',
+ 'Buttons',
+ 'Posters'));
+
+}
+
+
+function calculateTotalMensShirts() {
+ document.getElementById('mens_total').value =
+ getTotal( new Array('mens_s',
+ 'mens_m',
+ 'mens_l',
+ 'mens_xl',
+ 'mens_xxl',
+ 'mens_xxxl'));
+
+}
+
+
+function calculateTotalWomensShirts() {
+ document.getElementById('womens_total').value =
+ getTotal( new Array('womens_s',
+ 'womens_m',
+ 'womens_l',
+ 'womens_xl',
+ 'womens_xxl',
+ 'womens_xxxl'));
+
+}
diff --git a/extensions/BMO/web/js/triage_reports.js b/extensions/BMO/web/js/triage_reports.js
new file mode 100644
index 000000000..855b577d7
--- /dev/null
+++ b/extensions/BMO/web/js/triage_reports.js
@@ -0,0 +1,83 @@
+var Dom = YAHOO.util.Dom;
+
+function onSelectProduct() {
+ var component = Dom.get('component');
+ if (Dom.get('product').value == '') {
+ bz_clearOptions(component);
+ return;
+ }
+ selectProduct(Dom.get('product'), component);
+ // selectProduct only supports __Any__ on both elements
+ // we only want it on component, so add it back in
+ try {
+ component.add(new Option('__Any__', ''), component.options[0]);
+ } catch(e) {
+ // support IE
+ component.add(new Option('__Any__', ''), 0);
+ }
+ component.value = '';
+}
+
+function onCommenterChange() {
+ var commenter_is = Dom.get('commenter_is');
+ if (Dom.get('commenter').value == 'is') {
+ Dom.removeClass(commenter_is, 'hidden');
+ } else {
+ Dom.addClass(commenter_is, 'hidden');
+ }
+}
+
+function onLastChange() {
+ var last_is_span = Dom.get('last_is_span');
+ if (Dom.get('last').value == 'is') {
+ Dom.removeClass(last_is_span, 'hidden');
+ } else {
+ Dom.addClass(last_is_span, 'hidden');
+ }
+}
+
+function onGenerateReport() {
+ if (Dom.get('product').value == '') {
+ alert('You must select a product.');
+ return false;
+ }
+ if (Dom.get('component').value == '' && !Dom.get('component').options[0].selected) {
+ alert('You must select at least one component.');
+ return false;
+ }
+ if (!(Dom.get('filter_commenter').checked || Dom.get('filter_last').checked)) {
+ alert('You must select at least one comment filter.');
+ return false;
+ }
+ if (Dom.get('filter_commenter').checked
+ && Dom.get('commenter').value == 'is'
+ && Dom.get('commenter_is').value == '')
+ {
+ alert('You must specify the last commenter\'s email address.');
+ return false;
+ }
+ if (Dom.get('filter_last').checked
+ && Dom.get('last').value == 'is'
+ && Dom.get('last_is').value == '')
+ {
+ alert('You must specify the "comment is older than" date.');
+ return false;
+ }
+ return true;
+}
+
+YAHOO.util.Event.onDOMReady(function() {
+ onSelectProduct();
+ onCommenterChange();
+ onLastChange();
+
+ var component = Dom.get('component');
+ if (selected_components.length == 0)
+ return;
+ component.options[0].selected = false;
+ for (var i = 0, n = selected_components.length; i < n; i++) {
+ var index = bz_optionIndex(component, selected_components[i]);
+ if (index != -1)
+ component.options[index].selected = true;
+ }
+});
diff --git a/extensions/BMO/web/js/webtrends.js b/extensions/BMO/web/js/webtrends.js
new file mode 100644
index 000000000..fd0aca29e
--- /dev/null
+++ b/extensions/BMO/web/js/webtrends.js
@@ -0,0 +1,213 @@
+function WebTrends(options){var that=this;this.dcsid="dcsis0ifv10000gg3ag82u4rf_7b1e";this.rate=100;this.fpcdom=".mozilla.org";this.trackevents=false;if(typeof(options)!="undefined")
+{if(typeof(options.dcsid)!="undefined")this.dcsid=options.dcsid;if(typeof(options.rate)!="undefined")this.rate=options.rate;if(typeof(options.fpcdom)!="undefined")this.fpcdom=options.fpcdom;if(typeof(this.fpcdom)!="undefined"&&this.fpcdom.substring(0,1)!='.')this.fpcdom='.'+this.fpcdom;if(typeof(options.trackevents)!="undefined")this.trackevents=options.trackevents;}
+this.domain="statse.webtrendslive.com";this.timezone=0;this.onsitedoms="";this.downloadtypes="xls,doc,pdf,txt,csv,zip,dmg,exe";this.navigationtag="div,table";this.enabled=true;this.i18n=false;this.fpc="WT_FPC";this.paidsearchparams="gclid";this.splitvalue="";this.preserve=true;this.DCSdir={};this.DCS={};this.WT={};this.DCSext={};this.images=[];this.index=0;this.exre=(function()
+{return(window.RegExp?new RegExp("dcs(uri)|(ref)|(aut)|(met)|(sta)|(sip)|(pro)|(byt)|(dat)|(p3p)|(cfg)|(redirect)|(cip)","i"):"");})();this.re=(function()
+{return(window.RegExp?(that.i18n?{"%25":/\%/g,"%26":/\&/g}:{"%09":/\t/g,"%20":/ /g,"%23":/\#/g,"%26":/\&/g,"%2B":/\+/g,"%3F":/\?/g,"%5C":/\\/g,"%22":/\"/g,"%7F":/\x7F/g,"%A0":/\xA0/g}):"");})();}
+WebTrends.prototype.dcsGetId=function(){if(this.enabled&&(document.cookie.indexOf(this.fpc+"=")==-1)&&(document.cookie.indexOf("WTLOPTOUT=")==-1)){document.write("<scr"+"ipt type='text/javascript' src='"+"http"+(window.location.protocol.indexOf('https:')==0?'s':'')+"://"+this.domain+"/"+this.dcsid+"/wtid.js"+"'><\/scr"+"ipt>");}}
+WebTrends.prototype.dcsGetCookie=function(name)
+{var cookies=document.cookie.split("; ");var cmatch=[];var idx=0;var i=0;var namelen=name.length;var clen=cookies.length;for(i=0;i<clen;i++)
+{var c=cookies[i];if((c.substring(0,namelen+1))==(name+"=")){cmatch[idx++]=c;}}
+var cmatchCount=cmatch.length;if(cmatchCount>0)
+{idx=0;if((cmatchCount>1)&&(name==this.fpc))
+{var dLatest=new Date(0);for(i=0;i<cmatchCount;i++)
+{var lv=parseInt(this.dcsGetCrumb(cmatch[i],"lv"));var dLst=new Date(lv);if(dLst>dLatest)
+{dLatest.setTime(dLst.getTime());idx=i;}}}
+return unescape(cmatch[idx].substring(namelen+1));}
+else
+{return null;}}
+WebTrends.prototype.dcsGetCrumb=function(cval,crumb,sep){var aCookie=cval.split(sep||":");for(var i=0;i<aCookie.length;i++){var aCrumb=aCookie[i].split("=");if(crumb==aCrumb[0]){return aCrumb[1];}}
+return null;}
+WebTrends.prototype.dcsGetIdCrumb=function(cval,crumb){var id=cval.substring(0,cval.indexOf(":lv="));var aCrumb=id.split("=");for(var i=0;i<aCrumb.length;i++){if(crumb==aCrumb[0]){return aCrumb[1];}}
+return null;}
+WebTrends.prototype.dcsIsFpcSet=function(name,id,lv,ss){var c=this.dcsGetCookie(name);if(c){return((id==this.dcsGetIdCrumb(c,"id"))&&(lv==this.dcsGetCrumb(c,"lv"))&&(ss==this.dcsGetCrumb(c,"ss")))?0:3;}
+return 2;}
+WebTrends.prototype.dcsFPC=function(){if(document.cookie.indexOf("WTLOPTOUT=")!=-1){return;}
+var WT=this.WT;var name=this.fpc;var dCur=new Date();var adj=(dCur.getTimezoneOffset()*60000)+(this.timezone*3600000);dCur.setTime(dCur.getTime()+adj);var dExp=new Date(dCur.getTime()+315360000000);var dSes=new Date(dCur.getTime());WT.co_f=WT.vtid=WT.vtvs=WT.vt_f=WT.vt_f_a=WT.vt_f_s=WT.vt_f_d=WT.vt_f_tlh=WT.vt_f_tlv="";if(document.cookie.indexOf(name+"=")==-1){if((typeof(gWtId)!="undefined")&&(gWtId!="")){WT.co_f=gWtId;}
+else if((typeof(gTempWtId)!="undefined")&&(gTempWtId!="")){WT.co_f=gTempWtId;WT.vt_f="1";}
+else{WT.co_f="2";var curt=dCur.getTime().toString();for(var i=2;i<=(32-curt.length);i++){WT.co_f+=Math.floor(Math.random()*16.0).toString(16);}
+WT.co_f+=curt;WT.vt_f="1";}
+if(typeof(gWtAccountRollup)=="undefined"){WT.vt_f_a="1";}
+WT.vt_f_s=WT.vt_f_d="1";WT.vt_f_tlh=WT.vt_f_tlv="0";}
+else{var c=this.dcsGetCookie(name);var id=this.dcsGetIdCrumb(c,"id");var lv=parseInt(this.dcsGetCrumb(c,"lv"));var ss=parseInt(this.dcsGetCrumb(c,"ss"));if((id==null)||(id=="null")||isNaN(lv)||isNaN(ss)){return;}
+WT.co_f=id;var dLst=new Date(lv);WT.vt_f_tlh=Math.floor((dLst.getTime()-adj)/1000);dSes.setTime(ss);if((dCur.getTime()>(dLst.getTime()+1800000))||(dCur.getTime()>(dSes.getTime()+28800000))){WT.vt_f_tlv=Math.floor((dSes.getTime()-adj)/1000);dSes.setTime(dCur.getTime());WT.vt_f_s="1";}
+if((dCur.getDay()!=dLst.getDay())||(dCur.getMonth()!=dLst.getMonth())||(dCur.getYear()!=dLst.getYear())){WT.vt_f_d="1";}}
+WT.co_f=escape(WT.co_f);WT.vtid=(typeof(this.vtid)=="undefined")?WT.co_f:(this.vtid||"");WT.vtvs=(dSes.getTime()-adj).toString();var expiry="; expires="+dExp.toGMTString();var cur=dCur.getTime().toString();var ses=dSes.getTime().toString();document.cookie=name+"="+"id="+WT.co_f+":lv="+cur+":ss="+ses+expiry+"; path=/"+(((this.fpcdom!=""))?("; domain="+this.fpcdom):(""));var rc=this.dcsIsFpcSet(name,WT.co_f,cur,ses);if(rc!=0){WT.co_f=WT.vtvs=WT.vt_f_s=WT.vt_f_d=WT.vt_f_tlh=WT.vt_f_tlv="";if(typeof(this.vtid)=="undefined"){WT.vtid="";}
+WT.vt_f=WT.vt_f_a=rc;}}
+WebTrends.prototype.dcsIsOnsite=function(host){if(host.length>0){host=host.toLowerCase();if(host==window.location.hostname.toLowerCase()){return true;}
+if(typeof(this.onsitedoms.test)=="function"){return this.onsitedoms.test(host);}
+else if(this.onsitedoms.length>0){var doms=this.dcsSplit(this.onsitedoms);var len=doms.length;for(var i=0;i<len;i++){if(host==doms[i]){return true;}}}}
+return false;}
+WebTrends.prototype.dcsTypeMatch=function(pth,typelist){var type=pth.toLowerCase().substring(pth.lastIndexOf(".")+1,pth.length);var types=this.dcsSplit(typelist);var tlen=types.length;for(var i=0;i<tlen;i++){if(type==types[i]){return true;}}
+return false;}
+WebTrends.prototype.dcsEvt=function(evt,tag){var e=evt.target||evt.srcElement;while(e.tagName&&(e.tagName.toLowerCase()!=tag.toLowerCase())){e=e.parentElement||e.parentNode;}
+return e;}
+WebTrends.prototype.dcsNavigation=function(evt){var id="";var cname="";var elems=this.dcsSplit(this.navigationtag);var elen=elems.length;var i,e,elem;for(i=0;i<elen;i++)
+{elem=elems[i];if(elem.length)
+{e=this.dcsEvt(evt,elem);id=(e.getAttribute&&e.getAttribute("id"))?e.getAttribute("id"):"";cname=e.className||"";if(id.length||cname.length){break;}}}
+return id.length?id:cname;}
+WebTrends.prototype.dcsBind=function(event,func){if((typeof(func)=="function")&&document.body){if(document.body.addEventListener){document.body.addEventListener(event,func.wtbind(this),true);}
+else if(document.body.attachEvent){document.body.attachEvent("on"+event,func.wtbind(this));}}}
+WebTrends.prototype.dcsET=function(){var e=(navigator.appVersion.indexOf("MSIE")!=-1)?"click":"mousedown";this.dcsBind(e,this.dcsDownload);this.dcsBind("contextmenu",this.dcsRightClick);this.dcsBind(e,this.dcsLinkTrack);}
+WebTrends.prototype.dcsMultiTrack=function(){var args=dcsMultiTrack.arguments?dcsMultiTrack.arguments:arguments;if(args.length%2==0){this.dcsSaveProps(args);this.dcsSetProps(args);var dCurrent=new Date();this.DCS.dcsdat=dCurrent.getTime();this.dcsFPC();this.dcsTag();this.dcsRestoreProps();}}
+WebTrends.prototype.dcsLinkTrack=function(evt)
+{evt=evt||(window.event||"");if(evt&&((typeof(evt.which)!="number")||(evt.which==1)))
+{var e=this.dcsEvt(evt,"A");var f=this.dcsEvt(evt,"IMG");if(e.href&&e.protocol&&e.protocol.indexOf("http")!=-1&&!this.dcsLinkTrackException(e))
+{if((navigator.appVersion.indexOf("MSIE")==-1)&&((e.onclick)||(e.onmousedown)))
+{this.dcsSetVarCap(e);}
+var hn=e.hostname?(e.hostname.split(":")[0]):"";var qry=e.search?e.search.substring(e.search.indexOf("?")+1,e.search.length):"";var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var ti='';if(f.alt)
+{ti=f.alt;}
+else
+{if(document.all)
+{ti=e.title||e.innerText||e.innerHTML||"";}
+else
+{ti=e.title||e.text||e.innerHTML||"";}}
+hn=this.DCS.setvar_dcssip||hn;pth=this.DCS.setvar_dcsuri||pth;qry=this.DCS.setvar_dcsqry||qry;ti=this.WT.setvar_ti||ti;ti=this.dcsTrim(ti);this.WT.mc_id=this.WT.setvar_mc_id||"";this.WT.sp=this.WT.ad=this.DCS.setvar_dcsuri=this.DCS.setvar_dcssip=this.DCS.setvar_dcsqry=this.WT.setvar_ti=this.WT.setvar_mc_id="";this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry",this.trimoffsiteparams?"":qry,"DCS.dcsref",window.location,"WT.ti","Link:"+ti,"WT.dl","1","WT.nv",this.dcsNavigation(evt),"WT.sp","","WT.ad","","WT.AutoLinkTrack","1");this.DCS.dcssip=this.DCS.dcsuri=this.DCS.dcsqry=this.DCS.dcsref=this.WT.ti=this.WT.dl=this.WT.nv="";}}}
+WebTrends.prototype.dcsTrim=function(sString)
+{while(sString.substring(0,1)==' ')
+{sString=sString.substring(1,sString.length);}
+while(sString.substring(sString.length-1,sString.length)==' ')
+{sString=sString.substring(0,sString.length-1);}
+return sString;}
+WebTrends.prototype.dcsSetVarCap=function(e)
+{if(e.onclick)
+var gCap=e.onclick.toString();else if(e.onmousedown)
+var gCap=e.onmousedown.toString();var gStart=gCap.substring(gCap.indexOf("dcsSetVar(")+10,gCap.length)||gCap.substring(gCap.indexOf("_tag.dcsSetVar(")+16,gCap.length);var gEnd=gStart.substring(0,gStart.indexOf(");")).replace(/\s"/gi,"").replace(/"/gi,"");var gSplit=gEnd.split(",");if(gSplit.length!=-1)
+{for(var i=0;i<gSplit.length;i+=2)
+{if(gSplit[i].indexOf('WT.')==0)
+{if(this.dcsSetVarValidate(gSplit[i]))
+{this.WT["setvar_"+gSplit[i].substring(3)]=gSplit[i+1];}
+else
+{this.WT[gSplit[i].substring(3)]=gSplit[i+1];}}
+else if(gSplit[i].indexOf('DCS.')==0)
+{if(this.dcsSetVarValidate(gSplit[i]))
+{this.DCS["setvar_"+gSplit[i].substring(4)]=gSplit[i+1];}
+else
+{this.DCS[gSplit[i].substring(4)]=gSplit[i+1];}}
+else if(gSplit[i].indexOf('DCSext.')==0)
+{if(this.dcsSetVarValidate(gSplit[i]))
+{this.DCSext["setvar_"+gSplit[i].substring(7)]=gSplit[i+1];}
+else
+{this.DCSext[gSplit[i].substring(7)]=gSplit[i+1];}}
+else if(gSplit[i].indexOf('DCSdir.')==0)
+{if(this.dcsSetVarValidate(gSplit[i]))
+{this.DCSdir["setvar_"+gSplit[i].substring(7)]=gSplit[i+1];}
+else
+{this.DCSdir[gSplit[i].substring(7)]=gSplit[i+1];}}}}}
+WebTrends.prototype.dcsSetVarValidate=function(validate)
+{var wtParamList="DCS.dcssip,DCS.dcsuri,DCS.dcsqry,WT.ti,WT.mc_id".split(",");for(var i=0;i<wtParamList.length;i++)
+{if(wtParamList[i]==validate)
+{return 1;}}
+return 0;}
+WebTrends.prototype.dcsSetVar=function()
+{var args=dcsSetVar.arguments?dcsSetVar.arguments:arguments;if((args.length%2==0)&&(navigator.appVersion.indexOf("MSIE")!=-1)){for(var i=0;i<args.length;i+=2){if(args[i].indexOf('WT.')==0){if(this.dcsSetVarValidate(args[i])){this.WT["setvar_"+args[i].substring(3)]=args[i+1];}
+else{this.WT[args[i].substring(3)]=args[i+1];}}
+else if(args[i].indexOf('DCS.')==0){if(this.dcsSetVarValidate(args[i])){this.DCS["setvar_"+args[i].substring(4)]=args[i+1];}
+else{this.DCS[args[i].substring(4)]=args[i+1];}}
+else if(args[i].indexOf('DCSext.')==0){if(this.dcsSetVarValidate(args[i])){this.DCSext["setvar_"+args[i].substring(7)]=args[i+1];}
+else{this.DCSext[args[i].substring(7)]=args[i+1];}}
+else if(args[i].indexOf('DCSdir.')==0){if(this.dcsSetVarValidate(args[i])){this.DCSdir["setvar_"+args[i].substring(7)]=args[i+1];}
+else{this.DCSdir[args[i].substring(7)]=args[i+1];}}}}}
+WebTrends.prototype.dcsLinkTrackException=function(n)
+{try
+{var b=0;if(this.DCSdir.gTrackExceptions)
+{var e=this.DCSdir.gTrackExceptions.split(",");while(b!=1)
+{if(n.tagName&&n.tagName=="body")
+{b=1;return false}
+else
+{if(n.className)
+{var f=String(n.className).split(" ");for(var c=0;c<e.length;c++)for(var d=0;d<f.length;d++)
+{if(f[d]==e[c])
+{b=1;return true}}}}
+n=n.parentNode}}
+else
+{return false;}}
+catch(g){}}
+WebTrends.prototype.dcsCleanUp=function(){this.DCS={};this.WT={};this.DCSext={};if(arguments.length%2==0){this.dcsSetProps(arguments);}}
+WebTrends.prototype.dcsSetProps=function(args){for(var i=0;i<args.length;i+=2){if(args[i].indexOf('WT.')==0){this.WT[args[i].substring(3)]=args[i+1];}
+else if(args[i].indexOf('DCS.')==0){this.DCS[args[i].substring(4)]=args[i+1];}
+else if(args[i].indexOf('DCSext.')==0){this.DCSext[args[i].substring(7)]=args[i+1];}}}
+WebTrends.prototype.dcsSaveProps=function(args){var i,key,param;if(this.preserve){this.args=[];for(i=0;i<args.length;i+=2){param=args[i];if(param.indexOf('WT.')==0){key=param.substring(3);this.args[i]=param;this.args[i+1]=this.WT[key]||"";}
+else if(param.indexOf('DCS.')==0){key=param.substring(4);this.args[i]=param;this.args[i+1]=this.DCS[key]||"";}
+else if(param.indexOf('DCSext.')==0){key=param.substring(7);this.args[i]=param;this.args[i+1]=this.DCSext[key]||"";}}}}
+WebTrends.prototype.dcsRestoreProps=function(){if(this.preserve){this.dcsSetProps(this.args);this.args=[];}}
+WebTrends.prototype.dcsSplit=function(list){var items=list.toLowerCase().split(",");var len=items.length;for(var i=0;i<len;i++){items[i]=items[i].replace(/^\s*/,"").replace(/\s*$/,"");}
+return items;}
+WebTrends.prototype.dcsDownload=function(evt){evt=evt||(window.event||"");if(evt&&((typeof(evt.which)!="number")||(evt.which==1))){var e=this.dcsEvt(evt,"A");if(e.href){var hn=e.hostname?(e.hostname.split(":")[0]):"";if(this.dcsIsOnsite(hn)&&this.dcsTypeMatch(e.pathname,this.downloadtypes)){var qry=e.search?e.search.substring(e.search.indexOf("?")+1,e.search.length):"";var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var ttl="";var text=document.all?e.innerText:e.text;var img=this.dcsEvt(evt,"IMG");if(img.alt){ttl=img.alt;}
+else if(text){ttl=text;}
+else if(e.innerHTML){ttl=e.innerHTML;}
+this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry",e.search||"","WT.ti","Download:"+ttl,"WT.dl","20","WT.nv",this.dcsNavigation(evt));}}}}
+WebTrends.prototype.dcsRightClick=function(evt){evt=evt||(window.event||"");if(evt){var btn=evt.which||evt.button;if((btn!=1)||(navigator.userAgent.indexOf("Safari")!=-1)){var e=this.dcsEvt(evt,"A");if((typeof(e.href)!="undefined")&&e.href){if((typeof(e.protocol)!="undefined")&&e.protocol&&(e.protocol.indexOf("http")!=-1)){if((typeof(e.pathname)!="undefined")&&this.dcsTypeMatch(e.pathname,this.downloadtypes)){var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var hn=e.hostname?(e.hostname.split(":")[0]):"";this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry","","WT.ti","RightClick:"+pth,"WT.dl","25");}}}}}}
+WebTrends.prototype.dcsAdv=function(){if(this.trackevents&&(typeof(this.dcsET)=="function")){if(window.addEventListener){window.addEventListener("load",this.dcsET.wtbind(this),false);}
+else if(window.attachEvent){window.attachEvent("onload",this.dcsET.wtbind(this));}}
+this.dcsFPC();}
+WebTrends.prototype.dcsVar=function(){var dCurrent=new Date();var WT=this.WT;var DCS=this.DCS;WT.tz=parseInt(dCurrent.getTimezoneOffset()/60*-1)||"0";WT.bh=dCurrent.getHours()||"0";WT.ul=navigator.appName=="Netscape"?navigator.language:navigator.userLanguage;if(typeof(screen)=="object"){WT.cd=navigator.appName=="Netscape"?screen.pixelDepth:screen.colorDepth;WT.sr=screen.width+"x"+screen.height;}
+if(typeof(navigator.javaEnabled())=="boolean"){WT.jo=navigator.javaEnabled()?"Yes":"No";}
+if(document.title){if(window.RegExp){var tire=new RegExp("^"+window.location.protocol+"//"+window.location.hostname+"\\s-\\s");WT.ti=document.title.replace(tire,"");}
+else{WT.ti=document.title;}}
+WT.js="Yes";WT.jv=(function(){var agt=navigator.userAgent.toLowerCase();var major=parseInt(navigator.appVersion);var mac=(agt.indexOf("mac")!=-1);var ff=(agt.indexOf("firefox")!=-1);var ff0=(agt.indexOf("firefox/0.")!=-1);var ff10=(agt.indexOf("firefox/1.0")!=-1);var ff15=(agt.indexOf("firefox/1.5")!=-1);var ff20=(agt.indexOf("firefox/2.0")!=-1);var ff3up=(ff&&!ff0&&!ff10&!ff15&!ff20);var nn=(!ff&&(agt.indexOf("mozilla")!=-1)&&(agt.indexOf("compatible")==-1));var nn4=(nn&&(major==4));var nn6up=(nn&&(major>=5));var ie=((agt.indexOf("msie")!=-1)&&(agt.indexOf("opera")==-1));var ie4=(ie&&(major==4)&&(agt.indexOf("msie 4")!=-1));var ie5up=(ie&&!ie4);var op=(agt.indexOf("opera")!=-1);var op5=(agt.indexOf("opera 5")!=-1||agt.indexOf("opera/5")!=-1);var op6=(agt.indexOf("opera 6")!=-1||agt.indexOf("opera/6")!=-1);var op7up=(op&&!op5&&!op6);var jv="1.1";if(ff3up){jv="1.8";}
+else if(ff20){jv="1.7";}
+else if(ff15){jv="1.6";}
+else if(ff0||ff10||nn6up||op7up){jv="1.5";}
+else if((mac&&ie5up)||op6){jv="1.4";}
+else if(ie5up||nn4||op5){jv="1.3";}
+else if(ie4){jv="1.2";}
+return jv;})();WT.ct="unknown";if(document.body&&document.body.addBehavior){try{document.body.addBehavior("#default#clientCaps");WT.ct=document.body.connectionType||"unknown";document.body.addBehavior("#default#homePage");WT.hp=document.body.isHomePage(location.href)?"1":"0";}
+catch(e){}}
+if(document.all){WT.bs=document.body?document.body.offsetWidth+"x"+document.body.offsetHeight:"unknown";}
+else{WT.bs=window.innerWidth+"x"+window.innerHeight;}
+WT.fv=(function(){var i,flash;if(window.ActiveXObject){for(i=15;i>0;i--){try{flash=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);return i+".0";}
+catch(e){}}}
+else if(navigator.plugins&&navigator.plugins.length){for(i=0;i<navigator.plugins.length;i++){if(navigator.plugins[i].name.indexOf('Shockwave Flash')!=-1){return navigator.plugins[i].description.split(" ")[2];}}}
+return"Not enabled";})();WT.slv=(function(){var slv="Not enabled";try{if(navigator.userAgent.indexOf('MSIE')!=-1){var sli=new ActiveXObject('AgControl.AgControl');if(sli){slv="Unknown";}}
+else if(navigator.plugins["Silverlight Plug-In"]){slv="Unknown";}}
+catch(e){}
+if(slv!="Not enabled"){var i,m,M,F;if((typeof(Silverlight)=="object")&&(typeof(Silverlight.isInstalled)=="function")){for(i=9;i>0;i--){M=i;if(Silverlight.isInstalled(M+".0")){break;}
+if(slv==M){break;}}
+for(m=9;m>=0;m--){F=M+"."+m;if(Silverlight.isInstalled(F)){slv=F;break;}
+if(slv==F){break;}}}}
+return slv;})();if(this.i18n){if(typeof(document.defaultCharset)=="string"){WT.le=document.defaultCharset;}
+else if(typeof(document.characterSet)=="string"){WT.le=document.characterSet;}
+else{WT.le="unknown";}}
+WT.tv="9.3.0";WT.sp=this.splitvalue;WT.dl="0";WT.ssl=(window.location.protocol.indexOf('https:')==0)?"1":"0";DCS.dcsdat=dCurrent.getTime();DCS.dcssip=window.location.hostname;DCS.dcsuri=window.location.pathname;WT.es=DCS.dcssip+DCS.dcsuri;if(window.location.search){DCS.dcsqry=window.location.search;}
+if(DCS.dcsqry){var dcsqry=DCS.dcsqry.toLowerCase();var params=this.paidsearchparams.length?this.paidsearchparams.toLowerCase().split(","):[];for(var i=0;i<params.length;i++){if(dcsqry.indexOf(params[i]+"=")!=-1){WT.srch="1";break;}}}
+if((window.document.referrer!="")&&(window.document.referrer!="-")){if(!(navigator.appName=="Microsoft Internet Explorer"&&parseInt(navigator.appVersion)<4)){DCS.dcsref=window.document.referrer;}}}
+WebTrends.prototype.dcsEscape=function(S,REL){if(REL!=""){S=S.toString();for(var R in REL){if(REL[R]instanceof RegExp){S=S.replace(REL[R],R);}}
+return S;}
+else{return escape(S);}}
+WebTrends.prototype.dcsA=function(N,V){if(this.i18n&&(this.exre!="")&&!this.exre.test(N)){if(N=="dcsqry"){var newV="";var params=V.substring(1).split("&");for(var i=0;i<params.length;i++){var pair=params[i];var pos=pair.indexOf("=");if(pos!=-1){var key=pair.substring(0,pos);var val=pair.substring(pos+1);if(i!=0){newV+="&";}
+newV+=key+"="+this.dcsEncode(val);}}
+V=V.substring(0,1)+newV;}
+else{V=this.dcsEncode(V);}}
+return"&"+N+"="+this.dcsEscape(V,this.re);}
+WebTrends.prototype.dcsEncode=function(S){return(typeof(encodeURIComponent)=="function")?encodeURIComponent(S):escape(S);}
+WebTrends.prototype.dcsCreateImage=function(dcsSrc){if(document.images){this.images[this.index]=new Image();this.images[this.index].src=dcsSrc;this.index++;}
+else{document.write('<img alt="" border="0" name="DCSIMG" width="1" height="1" src="'+dcsSrc+'">');}}
+WebTrends.prototype.dcsMeta=function(){var elems;if(document.documentElement){elems=document.getElementsByTagName("meta");}
+else if(document.all){elems=document.all.tags("meta");}
+if(typeof(elems)!="undefined"){var length=elems.length;for(var i=0;i<length;i++){var name=elems.item(i).name;var content=elems.item(i).content;var equiv=elems.item(i).httpEquiv;if(name.length>0){if(name.toUpperCase().indexOf("WT.")==0){this.WT[name.substring(3)]=content;}
+else if(name.toUpperCase().indexOf("DCSEXT.")==0){this.DCSext[name.substring(7)]=content;}
+else if(name.toUpperCase().indexOf("DCSDIR.")==0){this.DCSdir[name.substring(7)]=content;}
+else if(name.toUpperCase().indexOf("DCS.")==0){this.DCS[name.substring(4)]=content;}}}}}
+WebTrends.prototype.dcsTag=function(){if(document.cookie.indexOf("WTLOPTOUT=")!=-1||!this.dcsChk()){return;}
+var WT=this.WT;var DCS=this.DCS;var DCSext=this.DCSext;var i18n=this.i18n;var P="http"+(window.location.protocol.indexOf('https:')==0?'s':'')+"://"+this.domain+(this.dcsid==""?'':'/'+this.dcsid)+"/dcs.gif?";if(i18n){WT.dep="";}
+for(var N in DCS){if(DCS[N]&&(typeof DCS[N]!="function")){P+=this.dcsA(N,DCS[N]);}}
+for(N in WT){if(WT[N]&&(typeof WT[N]!="function")){P+=this.dcsA("WT."+N,WT[N]);}}
+for(N in DCSext){if(DCSext[N]&&(typeof DCSext[N]!="function")){if(i18n){WT.dep=(WT.dep.length==0)?N:(WT.dep+";"+N);}
+P+=this.dcsA(N,DCSext[N]);}}
+if(i18n&&(WT.dep.length>0)){P+=this.dcsA("WT.dep",WT.dep);}
+if(P.length>2048&&navigator.userAgent.indexOf('MSIE')>=0){P=P.substring(0,2040)+"&WT.tu=1";}
+this.dcsCreateImage(P);this.WT.ad="";}
+WebTrends.prototype.dcsDebug=function(){var t=this;var i=t.images[0].src;var q=i.indexOf("?");var r=i.substring(0,q).split("/");var m="<b>Protocol</b><br><code>"+r[0]+"<br></code>";m+="<b>Domain</b><br><code>"+r[2]+"<br></code>";m+="<b>Path</b><br><code>/"+r[3]+"/"+r[4]+"<br></code>";m+="<b>Query Params</b><code>"+i.substring(q+1).replace(/\&/g,"<br>")+"</code>";m+="<br><b>Cookies</b><br><code>"+document.cookie.replace(/\;/g,"<br>")+"</code>";if(t.w&&!t.w.closed){t.w.close();}
+t.w=window.open("","dcsDebug","width=500,height=650,scrollbars=yes,resizable=yes");t.w.document.write(m);t.w.focus();}
+WebTrends.prototype.dcsCollect=function(){if(this.enabled){this.dcsVar();this.dcsMeta();this.dcsAdv();this.dcsBounce();if(typeof(this.dcsCustom)=="function"){this.dcsCustom();}
+this.dcsTag();}}
+function dcsMultiTrack(){if(typeof(_tag)!="undefined"){return(_tag.dcsMultiTrack());}}
+function dcsSetVar(){if(typeof(_tag)!="undefined"){return(_tag.dcsSetVar());}}
+function dcsDebug(){if(typeof(_tag)!="undefined"){return(_tag.dcsDebug());}}
+Function.prototype.wtbind=function(obj){var method=this;var temp=function(){return method.apply(obj,arguments);};return temp;}
+WebTrends.prototype.dcsBounce=function(){if(typeof(this.WT.vt_f_s)!="undefined"&&this.WT.vt_f_s==1){this.WT.z_bounce="1";}else{this.WT.z_bounce="0";}}
+WebTrends.prototype.dcsChk=function()
+{if(this.rate==100){return"true";}
+var cname='wtspl';cval=this.dcsGetCookie(cname);if(cval==null)
+{cval=Math.floor(Math.random()*1000000);var date=new Date();date.setTime(date.getTime()+(30*24*60*60*1000));document.cookie=cname+"="+cval+"; expires="+date.toGMTString()+"; path=/; domain="+this.fpcdom+";";}
+return((cval%1000)<(this.rate*10));} \ No newline at end of file
diff --git a/extensions/BMO/web/producticons/camino.png b/extensions/BMO/web/producticons/camino.png
new file mode 100644
index 000000000..c833b4d04
--- /dev/null
+++ b/extensions/BMO/web/producticons/camino.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/dino.png b/extensions/BMO/web/producticons/dino.png
new file mode 100644
index 000000000..9e0470a07
--- /dev/null
+++ b/extensions/BMO/web/producticons/dino.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/fennec.png b/extensions/BMO/web/producticons/fennec.png
new file mode 100644
index 000000000..ebad7e358
--- /dev/null
+++ b/extensions/BMO/web/producticons/fennec.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/firefox.png b/extensions/BMO/web/producticons/firefox.png
new file mode 100644
index 000000000..582a6952a
--- /dev/null
+++ b/extensions/BMO/web/producticons/firefox.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/idea.png b/extensions/BMO/web/producticons/idea.png
new file mode 100644
index 000000000..9480dce62
--- /dev/null
+++ b/extensions/BMO/web/producticons/idea.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/input.png b/extensions/BMO/web/producticons/input.png
new file mode 100644
index 000000000..81f355d85
--- /dev/null
+++ b/extensions/BMO/web/producticons/input.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/labs.png b/extensions/BMO/web/producticons/labs.png
new file mode 100644
index 000000000..346e0ef06
--- /dev/null
+++ b/extensions/BMO/web/producticons/labs.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/marketplace.png b/extensions/BMO/web/producticons/marketplace.png
new file mode 100644
index 000000000..62025a2a8
--- /dev/null
+++ b/extensions/BMO/web/producticons/marketplace.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/mozilla.png b/extensions/BMO/web/producticons/mozilla.png
new file mode 100644
index 000000000..e506328bc
--- /dev/null
+++ b/extensions/BMO/web/producticons/mozilla.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/other.png b/extensions/BMO/web/producticons/other.png
new file mode 100644
index 000000000..e436c22ae
--- /dev/null
+++ b/extensions/BMO/web/producticons/other.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/seamonkey.png b/extensions/BMO/web/producticons/seamonkey.png
new file mode 100644
index 000000000..fcb261ae1
--- /dev/null
+++ b/extensions/BMO/web/producticons/seamonkey.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/sunbird.png b/extensions/BMO/web/producticons/sunbird.png
new file mode 100644
index 000000000..6b15c257d
--- /dev/null
+++ b/extensions/BMO/web/producticons/sunbird.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/thunderbird.png b/extensions/BMO/web/producticons/thunderbird.png
new file mode 100644
index 000000000..f3523183a
--- /dev/null
+++ b/extensions/BMO/web/producticons/thunderbird.png
Binary files differ
diff --git a/extensions/BMO/web/styles/choose_product.css b/extensions/BMO/web/styles/choose_product.css
new file mode 100644
index 000000000..053af542f
--- /dev/null
+++ b/extensions/BMO/web/styles/choose_product.css
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#choose_product h2,
+#choose_product p {
+ text-align: center;
+}
+
+#choose_product td h2,
+#choose_product td p {
+ text-align: left;
+}
diff --git a/extensions/BMO/web/styles/create_account.css b/extensions/BMO/web/styles/create_account.css
new file mode 100644
index 000000000..0ab527629
--- /dev/null
+++ b/extensions/BMO/web/styles/create_account.css
@@ -0,0 +1,62 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#create-account h2 {
+ margin: 0px;
+}
+
+.column-header {
+ padding: 20px 20px 20px 0px;
+}
+
+#create-account-left {
+ border-right: 2px solid #888888;
+ padding-right: 10px;
+}
+
+#product-list td {
+ padding-top: 10px;
+}
+
+#product-list img {
+ padding-right: 10px;
+}
+
+#create-account-right {
+ padding-left: 10px;
+}
+
+#right-blurb {
+ font-size: large;
+}
+
+#right-blurb li {
+ padding-bottom: 1em;
+}
+
+#create-account-right {
+ padding-bottom: 5em;
+}
+
diff --git a/extensions/BMO/web/styles/edit_bug.css b/extensions/BMO/web/styles/edit_bug.css
new file mode 100644
index 000000000..24212270d
--- /dev/null
+++ b/extensions/BMO/web/styles/edit_bug.css
@@ -0,0 +1,49 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the BMO Bugzilla Extension;
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#project-flags,
+#custom-flags {
+ width: auto;
+}
+
+.bz_hidden {
+ display: none;
+}
+
+.bz_collapse_comment {
+ font-family: monospace;
+}
+
+#prod_desc_container,
+#comp_desc_container {
+ overflow: auto;
+ color: green;
+ padding: 2px;
+}
+
+#toggle_prod_desc,
+#toggle_comp_desc {
+ white-space: nowrap;
+}
diff --git a/extensions/BMO/web/styles/reports.css b/extensions/BMO/web/styles/reports.css
new file mode 100644
index 000000000..7ad0df241
--- /dev/null
+++ b/extensions/BMO/web/styles/reports.css
@@ -0,0 +1,66 @@
+.hidden {
+ display: none;
+}
+
+#product, #component {
+ width: 20em;
+}
+
+#parameters th {
+ text-align: left;
+ vertical-align: middle !important;
+}
+
+#report tr.bugitem:hover {
+ background: #ccccff;
+}
+
+#report td, #report th {
+ padding: 3px 10px 3px 3px;
+}
+
+#report th {
+ text-align: left;
+}
+
+#report th.right {
+ text-align: right;
+}
+
+#report th.sorted {
+ text-decoration: underline;
+}
+
+#report-header {
+ background: #cccccc;
+}
+
+.report_row_odd {
+ background-color: #eeeeee;
+ color: #000000;
+}
+
+.report_row_even {
+ background-color: #ffffff;
+ color: #000000;
+}
+
+#report.hover tr:hover {
+ background-color: #ccccff;
+}
+
+#report {
+ border: 1px solid #888888;
+}
+
+#report th, #report td {
+ border: 0px;
+}
+
+.disabled {
+ color: #888888;
+}
+
+.hoverrow tr:hover {
+ background-color: #ccccff;
+}
diff --git a/extensions/BMO/web/styles/triage_reports.css b/extensions/BMO/web/styles/triage_reports.css
new file mode 100644
index 000000000..6190fd32c
--- /dev/null
+++ b/extensions/BMO/web/styles/triage_reports.css
@@ -0,0 +1,23 @@
+.hidden {
+ display: none;
+}
+
+#triage_form th {
+ text-align: left;
+}
+
+#product, #component {
+ width: 20em;
+}
+
+#report tr.bugitem:hover {
+ background: #ccccff;
+}
+
+#report td {
+ padding: 1px 10px 1px 10px;
+}
+
+#report-header {
+ background: #dddddd;
+}
diff --git a/extensions/BmpConvert/disabled b/extensions/BMO/web/yui-history-iframe.txt
index e69de29bb..e69de29bb 100644
--- a/extensions/BmpConvert/disabled
+++ b/extensions/BMO/web/yui-history-iframe.txt
diff --git a/extensions/BzAPI/Config.pm b/extensions/BzAPI/Config.pm
new file mode 100644
index 000000000..0de081097
--- /dev/null
+++ b/extensions/BzAPI/Config.pm
@@ -0,0 +1,63 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the BzAPI Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+package Bugzilla::Extension::BzAPI;
+use strict;
+
+use constant NAME => 'BzAPI';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'SOAP-Lite',
+ module => 'SOAP::Lite',
+ # 0.710.04 is required for correct UTF-8 handling, but .04 and .05 are
+ # affected by bug 468009.
+ version => '0.710.06',
+ },
+ {
+ package => 'Test-Taint',
+ module => 'Test::Taint',
+ version => 0,
+ },
+ {
+ package => 'JSON',
+ module => 'JSON',
+ version => 0,
+ },
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/BzAPI/Extension.pm b/extensions/BzAPI/Extension.pm
new file mode 100644
index 000000000..aeaa0bce4
--- /dev/null
+++ b/extensions/BzAPI/Extension.pm
@@ -0,0 +1,71 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the BzAPI Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+package Bugzilla::Extension::BzAPI;
+use strict;
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '0.1';
+
+# Add JSON filter for JSON templates
+sub template_before_create {
+ my ($self, $args) = @_;
+ my $config = $args->{'config'};
+
+ $config->{'FILTERS'}->{'json'} = sub {
+ my ($var) = @_;
+ $var =~ s/([\\\"\/])/\\$1/g;
+ $var =~ s/\n/\\n/g;
+ $var =~ s/\r/\\r/g;
+ $var =~ s/\f/\\f/g;
+ $var =~ s/\t/\\t/g;
+ return $var;
+ };
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $vars = $args->{'vars'};
+ my $file = $args->{'file'};
+
+ if ($file =~ /config\.json\.tmpl$/) {
+ $vars->{'initial_status'} = Bugzilla::Status->can_change_to;
+ $vars->{'status_objects'} = [Bugzilla::Status->get_all];
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/BzAPI/template/en/default/config.json.tmpl b/extensions/BzAPI/template/en/default/config.json.tmpl
new file mode 100644
index 000000000..9c6852346
--- /dev/null
+++ b/extensions/BzAPI/template/en/default/config.json.tmpl
@@ -0,0 +1,315 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ #%]
+
+[%
+ # Pinched from Bugzilla/API/Model/Utils.pm in BzAPI - need to keep in sync
+OLD2NEW = {
+ 'opendate' => 'creation_time', # query
+ 'creation_ts' => 'creation_time',
+ 'changeddate' => 'last_change_time', # query
+ 'delta_ts' => 'last_change_time',
+ 'bug_id' => 'id',
+ 'rep_platform' => 'platform',
+ 'bug_severity' => 'severity',
+ 'bug_status' => 'status',
+ 'short_desc' => 'summary',
+ 'short_short_desc' => 'summary',
+ 'bug_file_loc' => 'url',
+ 'status_whiteboard' => 'whiteboard',
+ 'reporter' => 'creator',
+ 'reporter_realname' => 'creator_realname',
+ 'cclist_accessible' => 'is_cc_accessible',
+ 'reporter_accessible' => 'is_creator_accessible',
+ 'everconfirmed' => 'is_confirmed',
+ 'dependson' => 'depends_on',
+ 'blocked' => 'blocks',
+ 'attachment' => 'attachments',
+ 'flag' => 'flags',
+ 'flagtypes.name' => 'flag',
+ 'bug_group' => 'group',
+ 'group' => 'groups',
+ 'longdesc' => 'comment',
+ 'bug_file_loc_type' => 'url_type',
+ 'bugidtype' => 'id_mode',
+ 'longdesc_type' => 'comment_type',
+ 'short_desc_type' => 'summary_type',
+ 'status_whiteboard_type' => 'whiteboard_type',
+ 'emailassigned_to1' => 'email1_assigned_to',
+ 'emailassigned_to2' => 'email2_assigned_to',
+ 'emailcc1' => 'email1_cc',
+ 'emailcc2' => 'email2_cc',
+ 'emailqa_contact1' => 'email1_qa_contact',
+ 'emailqa_contact2' => 'email2_qa_contact',
+ 'emailreporter1' => 'email1_creator',
+ 'emailreporter2' => 'email2_creator',
+ 'emaillongdesc1' => 'email1_comment_creator',
+ 'emaillongdesc2' => 'email2_comment_creator',
+ 'emailtype1' => 'email1_type',
+ 'emailtype2' => 'email2_type',
+ 'chfieldfrom' => 'changed_after',
+ 'chfieldto' => 'changed_before',
+ 'chfield' => 'changed_field',
+ 'chfieldvalue' => 'changed_field_to',
+ 'deadlinefrom' => 'deadline_after',
+ 'deadlineto' => 'deadline_before',
+ 'attach_data.thedata' => 'attachment.data',
+ 'longdescs.isprivate' => 'comment.is_private',
+ 'commenter' => 'comment.creator',
+ 'flagtypes.name' => 'flag',
+ 'requestees.login_name' => 'flag.requestee',
+ 'setters.login_name' => 'flag.setter',
+ 'days_elapsed' => 'idle',
+ 'owner_idle_time' => 'assignee_idle',
+ 'dup_id' => 'dupe_of',
+ 'isopened' => 'is_open',
+ 'flag_type' => 'flag_types',
+ 'token' => 'update_token'
+};
+
+OLDATTACH2NEW = {
+ 'submitter' => 'attacher',
+ 'description' => 'description',
+ 'filename' => 'file_name',
+ 'delta_ts' => 'last_change_time',
+ 'isobsolete' => 'is_obsolete',
+ 'ispatch' => 'is_patch',
+ 'isprivate' => 'is_private',
+ 'mimetype' => 'content_type',
+ 'contenttypeentry' => 'content_type',
+ 'date' => 'creation_time',
+ 'attachid' => 'id',
+ 'desc' => 'description',
+ 'flag' => 'flags',
+ 'type' => 'content_type',
+ 'token' => 'update_token'
+};
+
+%]
+
+[%# Add attachment stuff to the main hash - but with right prefix. (This is
+ # the way the code is structured in BzAPI, and changing it makes it harder
+ # to keep the two in sync.)
+ #%]
+[% FOREACH entry IN OLDATTACH2NEW %]
+ [% newkey = 'attachments.' _ entry.key %]
+ [% OLD2NEW.${newkey} = 'attachment.' _ OLDATTACH2NEW.${entry.key} %]
+[% END %]
+
+[% all_visible_flag_types = {} %]
+
+{
+ "version": "[% constants.BUGZILLA_VERSION FILTER json %]",
+ "maintainer": "[% Param('maintainer') FILTER json %]",
+ "announcement": "[% Param('announcehtml') FILTER json %]",
+ "max_attachment_size": [% (Param('maxattachmentsize') * 1000) FILTER json %],
+
+[% IF Param('useclassification') %]
+ [% cl_name_for = {} %]
+ "classification": {
+ [% FOREACH cl IN user.get_selectable_classifications() %]
+ [% cl_name_for.${cl.id} = cl.name %]
+ "[% cl.name FILTER json %]": {
+ "id": [% cl.id FILTER json %],
+ "description": "[% cl.description FILTER json %]",
+ "products": [
+ [% FOREACH product IN user.get_selectable_products(cl.id) %]
+ "[% product.name FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ]
+ }[% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+[% END %]
+
+ "product": {
+ [% FOREACH product = products %]
+ "[% product.name FILTER json %]": {
+ "id": [% product.id FILTER json %],
+ "description": "[% product.description FILTER json %]",
+ "is_active": [% product.isactive ? "true" : "false" %],
+ "is_permitting_unconfirmed": [% product.allows_unconfirmed ? "true" : "false" %],
+[% IF Param('useclassification') %]
+ "classification": "[% cl_name_for.${product.classification_id} FILTER json %]",
+[% END %]
+ "component": {
+ [% FOREACH component = product.components %]
+ "[% component.name FILTER json %]": {
+ "id": [% component.id FILTER json %],
+[% IF show_flags %]
+ "flag_type": [
+ [% flag_types =
+ component.flag_types(is_active=>1).bug.merge(component.flag_types(is_active=>1).attachment) %]
+ [%-# "first" flag used to get commas right; can't use loop.last() in case
+ # last flag is inactive %]
+ [% first = 1 %]
+ [% FOREACH flag_type = flag_types %]
+ [% all_visible_flag_types.${flag_type.id} = flag_type %]
+ [% ',' UNLESS first %][% flag_type.id FILTER json %][% first = 0 %]
+ [% END %]],
+[% END %]
+ "description": "[% component.description FILTER json %]"
+ } [% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+ "version": [
+ [% FOREACH version = product.versions %]
+ "[% version.name FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+
+[% IF Param('usetargetmilestone') %]
+ "default_target_milestone": "[% product.defaultmilestone FILTER json %]",
+ "target_milestone": [
+ [% FOREACH milestone = product.milestones %]
+ "[% milestone.name FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+[% END %]
+
+ "group": [
+ [% FOREACH group = product.groups_valid %]
+ [% group.id FILTER json %][% ',' UNLESS loop.last() %]
+ [% END %]
+ ]
+ }[% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+
+ "group": {
+ [% FOREACH group = product.groups_valid %]
+ "[% group.id FILTER json %]": {
+ "name": "[% group.name FILTER json %]",
+ "description": "[% group.description FILTER json %]",
+ "is_accepting_bugs": [% group.is_bug_group ? 'true' : 'false' %],
+ "is_active": [% group.is_active ? 'true' : 'false' %]
+ }[% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+
+[% IF show_flags %]
+ "flag_type": {
+ [% FOREACH flag_type = all_visible_flag_types.values.sort('name') %]
+ "[%+ flag_type.id FILTER json %]": {
+ "name": "[% flag_type.name FILTER json %]",
+ "description": "[% flag_type.description FILTER json %]",
+ [% IF user.in_group("editcomponents") %]
+ [% IF flag_type.request_group_id %]
+ "request_group": [% flag_type.request_group_id FILTER json %],
+ [% END %]
+ [% IF flag_type.grant_group_id %]
+ "grant_group": [% flag_type.grant_group_id FILTER json %],
+ [% END %]
+ [% END %]
+ "is_for_bugs": [% flag_type.target_type == "bug" ? 'true' : 'false' %],
+ "is_requestable": [% flag_type.is_requestable ? 'true' : 'false' %],
+ "is_specifically_requestable": [% flag_type.is_requesteeble ? 'true' : 'false' %],
+ "is_multiplicable": [% flag_type.is_multiplicable ? 'true' : 'false' %]
+ }[% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+[% END %]
+
+ [% PROCESS "global/field-descs.none.tmpl" %]
+
+ [%# Put custom field value data where below loop expects to find it %]
+ [% FOREACH cf = custom_fields %]
+ [% ${cf.name} = [] %]
+ [% FOREACH value = cf.legal_values %]
+ [% ${cf.name}.push(value.name) %]
+ [% END %]
+ [% END %]
+
+ [%# Built-in fields do not have type IDs. There aren't ID values for all
+ # the types of the built-in fields, but we do what we can, and leave the
+ # rest as "0" (unknown).
+ #%]
+ [% type_id_for = {
+ "id" => 6,
+ "summary" => 1,
+ "classification" => 2,
+ "version" => 2,
+ "url" => 1,
+ "whiteboard" => 1,
+ "keywords" => 3,
+ "component" => 2,
+ "attachment.description" => 1,
+ "attachment.file_name" => 1,
+ "attachment.content_type" => 1,
+ "target_milestone" => 2,
+ "comment" => 4,
+ "alias" => 1,
+ "deadline" => 5,
+ } %]
+
+ "field": {
+ [% FOREACH item = field %]
+ [% newname = OLD2NEW.${item.name} || item.name %]
+ "[% newname FILTER json %]": {
+ "description": "[% (field_descs.${item.name} OR
+ item.description) FILTER json %]",
+ "is_active": [% field.obsolete ? "false" : "true" %],
+ [% blacklist = ["version", "group", "product", "component"] %]
+ [% IF ${newname} AND NOT blacklist.contains(newname) %]
+ "values": [
+ [% FOREACH value = ${newname} %]
+ "[% value FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+ [% END %]
+ [% paramname = newname.replace("_", "") %] [%# For op_sys... %]
+ [% IF paramname != "query" AND Param('default' _ paramname) %]
+ "default": "[% Param('default' _ paramname) %]",
+ [% END %]
+ [%-# The 'status' hash has a lot of extra stuff %]
+ [% IF newname == "status" %]
+ "open": [
+ [% FOREACH value = open_status %]
+ "[% value FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+ "closed": [
+ [% FOREACH value = closed_status %]
+ "[% value FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+ "transitions": {
+ "{Start}": [
+ [% FOREACH target = initial_status %]
+ "[% target.name FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ],
+ [% FOREACH status = status_objects %]
+ [% targets = status.can_change_to() %]
+ "[% status.name FILTER json %]": [
+ [% FOREACH target = targets %]
+ "[% target.name FILTER json %]"[% ',' UNLESS loop.last() %]
+ [% END %]
+ ][% ',' UNLESS loop.last() %]
+ [% END %]
+ },
+ [% END %]
+ [% IF newname.match("^cf_") %]
+ "is_on_bug_entry": [% item.enter_bug ? 'true' : 'false' %],
+ [% END %]
+ "type": [% item.type || type_id_for.$newname || 0 FILTER json %]
+ }[% ',' UNLESS loop.last() %]
+ [% END %]
+ }
+}
diff --git a/extensions/ComponentWatching/Config.pm b/extensions/ComponentWatching/Config.pm
new file mode 100644
index 000000000..560b5c3c5
--- /dev/null
+++ b/extensions/ComponentWatching/Config.pm
@@ -0,0 +1,12 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ComponentWatching;
+use strict;
+use constant NAME => 'ComponentWatching';
+
+__PACKAGE__->NAME;
diff --git a/extensions/ComponentWatching/Extension.pm b/extensions/ComponentWatching/Extension.pm
new file mode 100644
index 000000000..45d6127bf
--- /dev/null
+++ b/extensions/ComponentWatching/Extension.pm
@@ -0,0 +1,498 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ComponentWatching;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Group;
+use Bugzilla::User;
+use Bugzilla::User::Setting;
+use Bugzilla::Util qw(trim);
+
+our $VERSION = '2';
+
+use constant REL_COMPONENT_WATCHER => 15;
+
+#
+# installation
+#
+
+sub db_schema_abstract_schema {
+ my ($self, $args) = @_;
+ $args->{'schema'}->{'component_watch'} = {
+ FIELDS => [
+ user_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ REFERENCES => {
+ TABLE => 'profiles',
+ COLUMN => 'userid',
+ DELETE => 'CASCADE',
+ }
+ },
+ component_id => {
+ TYPE => 'INT2',
+ NOTNULL => 0,
+ REFERENCES => {
+ TABLE => 'components',
+ COLUMN => 'id',
+ DELETE => 'CASCADE',
+ }
+ },
+ product_id => {
+ TYPE => 'INT2',
+ NOTNULL => 0,
+ REFERENCES => {
+ TABLE => 'products',
+ COLUMN => 'id',
+ DELETE => 'CASCADE',
+ }
+ },
+ ],
+ };
+}
+
+sub install_update_db {
+ my $dbh = Bugzilla->dbh;
+ $dbh->bz_add_column(
+ 'components',
+ 'watch_user',
+ {
+ TYPE => 'INT3',
+ REFERENCES => {
+ TABLE => 'profiles',
+ COLUMN => 'userid',
+ DELETE => 'SET NULL',
+ }
+ }
+ );
+}
+
+#
+# templates
+#
+
+sub template_before_create {
+ my ($self, $args) = @_;
+ my $config = $args->{config};
+ my $constants = $config->{CONSTANTS};
+ $constants->{REL_COMPONENT_WATCHER} = REL_COMPONENT_WATCHER;
+}
+
+#
+# user-watch
+#
+
+BEGIN {
+ *Bugzilla::Component::watch_user = \&_component_watch_user;
+}
+
+sub _component_watch_user {
+ my ($self) = @_;
+ return unless $self->{watch_user};
+ $self->{watch_user_object} ||= Bugzilla::User->new($self->{watch_user});
+ return $self->{watch_user_object};
+}
+
+sub object_columns {
+ my ($self, $args) = @_;
+ my $class = $args->{class};
+ my $columns = $args->{columns};
+ return unless $class->isa('Bugzilla::Component');
+
+ push(@$columns, 'watch_user');
+}
+
+sub object_update_columns {
+ my ($self, $args) = @_;
+ my $object = $args->{object};
+ my $columns = $args->{columns};
+ return unless $object->isa('Bugzilla::Component');
+
+ push(@$columns, 'watch_user');
+
+ # editcomponents.cgi doesn't call set_all, so we have to do this here
+ my $input = Bugzilla->input_params;
+ $object->set('watch_user', $input->{watch_user});
+}
+
+sub object_validators {
+ my ($self, $args) = @_;
+ my $class = $args->{class};
+ my $validators = $args->{validators};
+ return unless $class->isa('Bugzilla::Component');
+
+ $validators->{watch_user} = \&_check_watch_user;
+}
+
+sub object_before_create {
+ my ($self, $args) = @_;
+ my $class = $args->{class};
+ my $params = $args->{params};
+ return unless $class->isa('Bugzilla::Component');
+
+ my $input = Bugzilla->input_params;
+ $params->{watch_user} = $input->{watch_user};
+}
+
+sub object_end_of_update {
+ my ($self, $args) = @_;
+ my $object = $args->{object};
+ my $old_object = $args->{old_object};
+ my $changes = $args->{changes};
+ return unless $object->isa('Bugzilla::Component');
+
+ my $old_id = $old_object->watch_user ? $old_object->watch_user->id : 0;
+ my $new_id = $object->watch_user ? $object->watch_user->id : 0;
+ return if $old_id == $new_id;
+
+ $changes->{watch_user} = [ $old_id ? $old_id : undef, $new_id ? $new_id : undef ];
+}
+
+sub _check_watch_user {
+ my ($self, $value, $field) = @_;
+ $value = trim($value || '');
+ if ($value eq '') {
+ ThrowUserError('component_watch_missing_watch_user');
+ }
+ if ($value !~ /\.bugs$/i) {
+ ThrowUserError('component_watch_invalid_watch_user');
+ }
+ return Bugzilla::User->check($value)->id;
+}
+
+#
+# preferences
+#
+
+sub user_preferences {
+ my ($self, $args) = @_;
+ my $tab = $args->{'current_tab'};
+ return unless $tab eq 'component_watch';
+
+ my $save = $args->{'save_changes'};
+ my $handled = $args->{'handled'};
+ my $vars = $args->{'vars'};
+ my $user = Bugzilla->user;
+ my $input = Bugzilla->input_params;
+
+ if ($save) {
+ my ($sth, $sthAdd, $sthDel);
+
+ if ($input->{'add'} && $input->{'add_product'}) {
+ # add watch
+
+ my $productName = $input->{'add_product'};
+ my $ra_componentNames = $input->{'add_component'};
+ $ra_componentNames = [$ra_componentNames || ''] unless ref($ra_componentNames);
+
+ # load product and verify access
+ my $product = Bugzilla::Product->new({ name => $productName });
+ unless ($product && $user->can_access_product($product)) {
+ ThrowUserError('product_access_denied', { product => $productName });
+ }
+
+ if (grep { $_ eq '' } @$ra_componentNames) {
+ # watching a product
+ _addProductWatch($user, $product);
+
+ } else {
+ # watching specific components
+ foreach my $componentName (@$ra_componentNames) {
+ my $component = Bugzilla::Component->new({ name => $componentName, product => $product });
+ unless ($component) {
+ ThrowUserError('product_access_denied', { product => $productName });
+ }
+ _addComponentWatch($user, $component);
+ }
+ }
+
+ _addDefaultSettings($user);
+
+ } else {
+ # remove watch(s)
+
+ foreach my $name (keys %$input) {
+ if ($name =~ /^del_(\d+)$/) {
+ _deleteProductWatch($user, $1);
+ } elsif ($name =~ /^del_(\d+)_(\d+)$/) {
+ _deleteComponentWatch($user, $1, $2);
+ }
+ }
+ }
+ }
+
+ $vars->{'add_product'} = $input->{'product'};
+ $vars->{'add_component'} = $input->{'component'};
+ $vars->{'watches'} = _getWatches($user);
+ $vars->{'user_watches'} = _getUserWatches($user);
+
+ $$handled = 1;
+}
+
+#
+# bugmail
+#
+
+sub bugmail_recipients {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+ my $recipients = $args->{'recipients'};
+ my $diffs = $args->{'diffs'};
+
+ my ($oldProductId, $newProductId) = ($bug->product_id, $bug->product_id);
+ my ($oldComponentId, $newComponentId) = ($bug->component_id, $bug->component_id);
+
+ # notify when the product/component is switch from one being watched
+ if (@$diffs) {
+ # we need the product to process the component, so scan for that first
+ my $product;
+ foreach my $ra (@$diffs) {
+ next if !(exists $ra->{'old'}
+ && exists $ra->{'field_name'});
+ if ($ra->{'field_name'} eq 'product') {
+ $product = Bugzilla::Product->new({ name => $ra->{'old'} });
+ $oldProductId = $product->id;
+ }
+ }
+ if (!$product) {
+ $product = Bugzilla::Product->new($oldProductId);
+ }
+ foreach my $ra (@$diffs) {
+ next if !(exists $ra->{'old'}
+ && exists $ra->{'field_name'});
+ if ($ra->{'field_name'} eq 'component') {
+ my $component = Bugzilla::Component->new({ name => $ra->{'old'}, product => $product });
+ $oldComponentId = $component->id;
+ }
+ }
+ }
+
+ # add component watchers
+ my $dbh = Bugzilla->dbh;
+ my $sth = $dbh->prepare("
+ SELECT user_id
+ FROM component_watch
+ WHERE ((product_id = ? OR product_id = ?) AND component_id IS NULL)
+ OR (component_id = ? OR component_id = ?)
+ ");
+ $sth->execute($oldProductId, $newProductId, $oldComponentId, $newComponentId);
+ while (my ($uid) = $sth->fetchrow_array) {
+ if (!exists $recipients->{$uid}) {
+ $recipients->{$uid}->{+REL_COMPONENT_WATCHER} = Bugzilla::BugMail::BIT_WATCHING();
+ }
+ }
+
+ # add component watchers from watch-users
+ my $uidList = join(',', keys %$recipients);
+ $sth = $dbh->prepare("
+ SELECT component_watch.user_id
+ FROM components
+ INNER JOIN component_watch ON component_watch.component_id = components.id
+ WHERE components.watch_user in ($uidList)
+ ");
+ $sth->execute();
+ while (my ($uid) = $sth->fetchrow_array) {
+ if (!exists $recipients->{$uid}) {
+ $recipients->{$uid}->{+REL_COMPONENT_WATCHER} = Bugzilla::BugMail::BIT_WATCHING();
+ }
+ }
+
+ # add watch-users from component watchers
+ $sth = $dbh->prepare("
+ SELECT watch_user
+ FROM components
+ WHERE (id = ? OR id = ?)
+ AND (watch_user IS NOT NULL)
+ ");
+ $sth->execute($oldComponentId, $newComponentId);
+ while (my ($uid) = $sth->fetchrow_array) {
+ if (!exists $recipients->{$uid}) {
+ $recipients->{$uid}->{+REL_COMPONENT_WATCHER} = Bugzilla::BugMail::BIT_DIRECT();
+ }
+ }
+}
+
+sub bugmail_relationships {
+ my ($self, $args) = @_;
+ my $relationships = $args->{relationships};
+ $relationships->{+REL_COMPONENT_WATCHER} = 'Component-Watcher';
+}
+
+#
+# db
+#
+
+sub _getWatches {
+ my ($user) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT product_id, component_id
+ FROM component_watch
+ WHERE user_id = ?
+ ");
+ $sth->execute($user->id);
+ my @watches;
+ while (my ($productId, $componentId) = $sth->fetchrow_array) {
+ my $product = Bugzilla::Product->new($productId);
+ next unless $product && $user->can_access_product($product);
+
+ my %watch = ( product => $product );
+ if ($componentId) {
+ my $component = Bugzilla::Component->new($componentId);
+ next unless $component;
+ $watch{'component'} = $component;
+ }
+
+ push @watches, \%watch;
+ }
+
+ @watches = sort {
+ $a->{'product'}->name cmp $b->{'product'}->name
+ || $a->{'component'}->name cmp $b->{'component'}->name
+ } @watches;
+
+ return \@watches;
+}
+
+sub _getUserWatches {
+ my ($user) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT components.product_id, components.id as component, profiles.login_name
+ FROM watch
+ INNER JOIN components ON components.watch_user = watched
+ INNER JOIN profiles ON profiles.userid = watched
+ WHERE watcher = ?
+ ");
+ $sth->execute($user->id);
+ my @watches;
+ while (my ($productId, $componentId, $login) = $sth->fetchrow_array) {
+ my $product = Bugzilla::Product->new($productId);
+ next unless $product && $user->can_access_product($product);
+
+ my %watch = (
+ product => $product,
+ component => Bugzilla::Component->new($componentId),
+ user => Bugzilla::User->check($login),
+ );
+ push @watches, \%watch;
+ }
+
+ @watches = sort {
+ $a->{'product'}->name cmp $b->{'product'}->name
+ || $a->{'component'}->name cmp $b->{'component'}->name
+ } @watches;
+
+ return \@watches;
+}
+
+sub _addProductWatch {
+ my ($user, $product) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT 1
+ FROM component_watch
+ WHERE user_id = ? AND product_id = ? AND component_id IS NULL
+ ");
+ $sth->execute($user->id, $product->id);
+ return if $sth->fetchrow_array;
+
+ $sth = $dbh->prepare("
+ DELETE FROM component_watch
+ WHERE user_id = ? AND product_id = ?
+ ");
+ $sth->execute($user->id, $product->id);
+
+ $sth = $dbh->prepare("
+ INSERT INTO component_watch(user_id, product_id)
+ VALUES (?, ?)
+ ");
+ $sth->execute($user->id, $product->id);
+}
+
+sub _addComponentWatch {
+ my ($user, $component) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT 1
+ FROM component_watch
+ WHERE user_id = ?
+ AND (component_id = ? OR (product_id = ? AND component_id IS NULL))
+ ");
+ $sth->execute($user->id, $component->id, $component->product_id);
+ return if $sth->fetchrow_array;
+
+ $sth = $dbh->prepare("
+ INSERT INTO component_watch(user_id, product_id, component_id)
+ VALUES (?, ?, ?)
+ ");
+ $sth->execute($user->id, $component->product_id, $component->id);
+}
+
+sub _deleteProductWatch {
+ my ($user, $productId) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ DELETE FROM component_watch
+ WHERE user_id = ? AND product_id = ? AND component_id IS NULL
+ ");
+ $sth->execute($user->id, $productId);
+}
+
+sub _deleteComponentWatch {
+ my ($user, $productId, $componentId) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ DELETE FROM component_watch
+ WHERE user_id = ? AND product_id = ? AND component_id = ?
+ ");
+ $sth->execute($user->id, $productId, $componentId);
+}
+
+sub _addDefaultSettings {
+ my ($user) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT 1
+ FROM email_setting
+ WHERE user_id = ? AND relationship = ?
+ ");
+ $sth->execute($user->id, REL_COMPONENT_WATCHER);
+ return if $sth->fetchrow_array;
+
+ my @defaultEvents = (
+ EVT_OTHER,
+ EVT_COMMENT,
+ EVT_ATTACHMENT,
+ EVT_ATTACHMENT_DATA,
+ EVT_PROJ_MANAGEMENT,
+ EVT_OPENED_CLOSED,
+ EVT_KEYWORD,
+ EVT_DEPEND_BLOCK,
+ EVT_BUG_CREATED,
+ );
+ foreach my $event (@defaultEvents) {
+ $dbh->do(
+ "INSERT INTO email_setting(user_id,relationship,event) VALUES (?,?,?)",
+ undef,
+ $user->id, REL_COMPONENT_WATCHER, $event
+ );
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/ComponentWatching/template/en/default/account/prefs/component_watch.html.tmpl b/extensions/ComponentWatching/template/en/default/account/prefs/component_watch.html.tmpl
new file mode 100644
index 000000000..8c193a056
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/account/prefs/component_watch.html.tmpl
@@ -0,0 +1,232 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%# initialise product to component mapping #%]
+
+[% SET selectable_products = user.get_selectable_products %]
+[% SET dont_show_button = 1 %]
+
+<script>
+var Dom = YAHOO.util.Dom;
+var useclassification = false;
+var first_load = true;
+var last_sel = [];
+var cpts = new Array();
+var watch_users = new Array();
+[% n = 0 %]
+[% FOREACH prod = selectable_products %]
+ cpts['[% n %]'] = [
+ [%- FOREACH comp = prod.components %]'[% comp.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
+ [% n = n + 1 %]
+ [% FOREACH comp = prod.components %]
+ [% IF comp.watch_user %]
+ if (!watch_users['[% prod.name FILTER js %]'])
+ watch_users['[% prod.name FILTER js %]'] = new Array();
+ watch_users['[% prod.name FILTER js %]']['[% comp.name FILTER js %]'] = '[% comp.watch_user.login FILTER js %]';
+ [% END %]
+ [% END %]
+[% END %]
+</script>
+<script type="text/javascript" src="[% 'js/productform.js' FILTER mtime FILTER html %]">
+</script>
+
+<script>
+function onSelectProduct() {
+ var component = Dom.get('component');
+ selectProduct(Dom.get('product'), component);
+ // selectProduct only supports __Any__ on both elements
+ // we only want it on component, so add it back in
+ try {
+ component.add(new Option('__Any__', ''), component.options[0]);
+ } catch(e) {
+ // support IE
+ component.add(new Option('__Any__', ''), 0);
+ }
+ if ('[% add_component FILTER js %]' != ''
+ && bz_valueSelected(Dom.get('product'), '[% add_product FILTER js %]')
+ ) {
+ var index = bz_optionIndex(Dom.get('component'), '[% add_component FILTER js %]');
+ if (index != -1)
+ Dom.get('component').options[index].selected = true;
+ }
+ onSelectComponent();
+}
+
+function onSelectComponent() {
+ var product_select = Dom.get('product');
+ var product = product_select.options[product_select.selectedIndex].value;
+ var component = Dom.get('component').value;
+ if (component && watch_users[product] && watch_users[product][component]) {
+ Dom.get('watch-user-email').innerHTML = watch_users[product][component];
+ Dom.get('watch-user-div').style.display = '';
+ } else {
+ Dom.get('watch-user-div').style.display = 'none';
+ }
+ Dom.get('add').disabled = Dom.get('component').selectedIndex == -1;
+}
+
+YAHOO.util.Event.onDOMReady(onSelectProduct);
+
+function onRemoveChange() {
+ var cbs = Dom.get('remove_table').getElementsByTagName('input');
+ for (var i = 0, l = cbs.length; i < l; i++) {
+ if (cbs[i].checked) {
+ Dom.get('remove').disabled = false;
+ return;
+ }
+ }
+ Dom.get('remove').disabled = true;
+}
+
+YAHOO.util.Event.onDOMReady(onRemoveChange);
+
+</script>
+
+<p>
+ Select the components you want to watch.
+ To watch all components in a product, watch "__Any__".<br>
+ Use <a href="userprefs.cgi?tab=email">Email Preferences</a> to filter which
+ notification emails you receive.
+</p>
+
+<table border="0" cellpadding="3" cellspacing="0">
+<tr>
+ <td align="right">Product:</td>
+ <td colspan="2">
+ <select name="add_product" id="product" onChange="onSelectProduct()">
+ [% FOREACH product IN selectable_products %]
+ <option [% 'selected' IF add_product == product.name %]>
+ [%~ product.name FILTER html %]</option>
+ [% END %]
+ </select>
+ </td>
+</tr>
+<tr>
+ <td align="right" valign="top">Component:</td>
+ <td>
+ <select name="add_component" id="component" multiple size="10" onChange="onSelectComponent()">
+ <option value="">__Any__</option>
+ [% FOREACH product IN selectable_products %]
+ [% FOREACH component IN product.components %]
+ <option [% 'selected' IF add_component == component.name %]>
+ [%~ component.name FILTER html %]</option>
+ [% END %]
+ [% END %]
+ </select>
+ </td>
+ <td valign="top">
+ <div id="watch-user-div"
+ title="You can also watch a component by following this user. [% ~%]
+ CC'ing this user on a [% terms.bug %] will trigger notifications to all watchers of this component."
+ style="cursor:help">
+ Watch User: <span id="watch-user-email"></span>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td>&nbsp;</td>
+ <td><input type="submit" id="add" name="add" value="Add"></td>
+</tr>
+</table>
+
+<hr>
+<p>
+ You are currently watching:
+</p>
+
+[% IF watches.size %]
+
+ <table border="0" cellpadding="3" cellspacing="0" id="remove_table">
+ <tr>
+ <td>&nbsp;</td>
+ <td><b>Product</b></td>
+ <td>&nbsp;<b>Component</b></td>
+ </tr>
+ [% FOREACH watch IN watches %]
+ <tr>
+ [% IF (watch.component) %]
+ <td>
+ <input type="checkbox" onChange="onRemoveChange()" id="cwdel_[% loop.count %]" value="1"
+ name="del_[% watch.product.id FILTER html %]_[% watch.component.id FILTER html %]">
+ </td>
+ <td>
+ <label for="cwdel_[% loop.count %]">
+ [% watch.component.product.name FILTER html %]
+ </label>
+ </td>
+ <td>&nbsp;
+ <a href="buglist.cgi?product=[% watch.product.name FILTER uri ~%]
+ &component=[% watch.component.name FILTER uri %]&resolution=---">
+ [% watch.component.name FILTER html %]
+ </a>
+ </td>
+ [% ELSE %]
+ <td>
+ <input type="checkbox" onChange="onRemoveChange()" id="cwdel_[% loop.count %]" value="1"
+ name="del_[% watch.product.id FILTER html %]" value="1">
+ </td>
+ <td>
+ <label for="cwdel_[% loop.count %]">
+ [% watch.product.name FILTER html %]
+ </label>
+ </td>
+ <td>&nbsp;
+ <a href="describecomponents.cgi?product=[% watch.product.name FILTER uri %]">
+ __Any__
+ </a>
+ </td>
+ [% END %]
+ </tr>
+ [% END %]
+ </table>
+
+ <input id="remove" type="submit" value="Remove Selected">
+
+[% ELSE %]
+
+ <p>
+ <i>You are not watching any components directly.</i>
+ </p>
+
+[% END %]
+
+[% IF user_watches.size %]
+
+ <hr>
+ <p>
+ [% watches.size ? "In addition," : "However," %]
+ you are watching the following components by watching users:
+ </p>
+
+ <table border="0" cellpadding="3" cellspacing="0">
+ <tr>
+ <td><b>User</b></td>
+ <td>&nbsp;<b>Product</b></td>
+ <td>&nbsp;<b>Component</b></td>
+ </tr>
+ [% FOREACH watch IN user_watches %]
+ <tr>
+ <td>[% watch.user.login FILTER html %]</td>
+ <td>&nbsp;[% watch.component.product.name FILTER html %]</td>
+ <td>&nbsp;
+ <a href="buglist.cgi?product=[% watch.product.name FILTER uri ~%]
+ &component=[% watch.component.name FILTER uri %]&resolution=---">
+ [% watch.component.name FILTER html %]
+ </a>
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+ <p>
+ Use <a href="userprefs.cgi?tab=email#new_watched_by_you">Email Preferences</a>
+ to manage this list.
+ </p>
+
+[% END %]
+
diff --git a/extensions/ComponentWatching/template/en/default/hook/account/prefs/email-relationships.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/account/prefs/email-relationships.html.tmpl
new file mode 100644
index 000000000..69ab53751
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/account/prefs/email-relationships.html.tmpl
@@ -0,0 +1,10 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% relationships.push({ id = constants.REL_COMPONENT_WATCHER, description = "Component" }) %]
+[% no_added_removed.push(constants.REL_COMPONENT_WATCHER) %]
diff --git a/extensions/ComponentWatching/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl
new file mode 100644
index 000000000..9af22ed39
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl
@@ -0,0 +1,14 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% tabs = tabs.import([{
+ name => "component_watch",
+ label => "Component Watching",
+ link => "userprefs.cgi?tab=component_watch",
+ saveable => 1
+ }]) %]
diff --git a/extensions/ComponentWatching/template/en/default/hook/admin/components/edit-common-rows.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/admin/components/edit-common-rows.html.tmpl
new file mode 100644
index 000000000..4f92097ff
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/admin/components/edit-common-rows.html.tmpl
@@ -0,0 +1,20 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<tr>
+ <th class="field_label"><label for="watch_user">Watch User:</label></th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ name => "watch_user"
+ id => "watch_user"
+ value => comp.watch_user.login
+ size => 64
+ emptyok => 1
+ %]
+ </td>
+</tr>
diff --git a/extensions/ComponentWatching/template/en/default/hook/admin/components/list-before_table.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/admin/components/list-before_table.html.tmpl
new file mode 100644
index 000000000..ed8d6e350
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/admin/components/list-before_table.html.tmpl
@@ -0,0 +1,17 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% CALL columns.splice(5, 0, { name => 'watch_user', heading => 'Watch User' }) %]
+
+[% FOREACH my_component = product.components %]
+ [% overrides.watch_user.name.${my_component.name} = {
+ override_content => 1
+ content => my_component.watch_user.login
+ }
+ %]
+[% END %]
diff --git a/extensions/ComponentWatching/template/en/default/hook/global/messages-component_updated_fields.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/global/messages-component_updated_fields.html.tmpl
new file mode 100644
index 000000000..38c7e8c8a
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/global/messages-component_updated_fields.html.tmpl
@@ -0,0 +1,15 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF changes.watch_user.defined %]
+ [% IF comp.watch_user %]
+ <li>Watch User updated to '[% comp.watch_user.login FILTER html %]'</li>
+ [% ELSE %]
+ <li>Watch User deleted</li>
+ [% END %]
+[% END %]
diff --git a/extensions/ComponentWatching/template/en/default/hook/global/reason-descs-end.none.tmpl b/extensions/ComponentWatching/template/en/default/hook/global/reason-descs-end.none.tmpl
new file mode 100644
index 000000000..8cd67bdff
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/global/reason-descs-end.none.tmpl
@@ -0,0 +1,10 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% watch_reason_descs.${constants.REL_COMPONENT_WATCHER} =
+ "You are watching the component for the ${terms.bug}." %]
diff --git a/extensions/ComponentWatching/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..01dbb5114
--- /dev/null
+++ b/extensions/ComponentWatching/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,17 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "component_watch_invalid_watch_user" %]
+ [% title = "Invalid Watch User" %]
+ The "Watch User" must be a <b>.bugs</b> email address.<br>
+ For example: <i>accessibility-apis@core.bugs</i>
+[% ELSIF error == "component_watch_missing_watch_user" %]
+ [% title = "Missing Watch User" %]
+ You must provide a <b>.bugs</b> email address for the "Watch User".<br>
+ For example: <i>accessibility-apis@core.bugs</i>
+[% END %]
diff --git a/extensions/ContributorEngagement/Config.pm b/extensions/ContributorEngagement/Config.pm
new file mode 100644
index 000000000..3984dd60e
--- /dev/null
+++ b/extensions/ContributorEngagement/Config.pm
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ContributorEngagement;
+use strict;
+
+use constant NAME => 'ContributorEngagement';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/ContributorEngagement/Extension.pm b/extensions/ContributorEngagement/Extension.pm
new file mode 100644
index 000000000..7e7031b33
--- /dev/null
+++ b/extensions/ContributorEngagement/Extension.pm
@@ -0,0 +1,134 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ContributorEngagement;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::User;
+use Bugzilla::Util qw(format_time);
+use Bugzilla::Mailer;
+use Bugzilla::Install::Util qw(indicate_progress);
+
+use Bugzilla::Extension::ContributorEngagement::Constants;
+
+our $VERSION = '1.0';
+
+BEGIN {
+ *Bugzilla::User::first_patch_approved_id = \&_first_patch_approved_id;
+}
+
+sub _first_patch_approved_id { return $_[0]->{'first_patch_approved_id'}; }
+
+sub install_update_db {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ if (!$dbh->bz_column_info('profiles', 'first_patch_approved_id')) {
+ $dbh->bz_add_column('profiles', 'first_patch_approved_id',
+ { TYPE => 'INT3' });
+ _migrate_first_approved_ids();
+ }
+}
+
+sub _migrate_first_approved_ids {
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare('UPDATE profiles SET first_patch_approved_id = ? WHERE userid = ?');
+ my $ra = $dbh->selectall_arrayref("SELECT attachments.submitter_id,
+ attachments.attach_id,
+ flagtypes.name
+ FROM attachments
+ INNER JOIN flags ON attachments.attach_id = flags.attach_id
+ INNER JOIN flagtypes ON flags.type_id = flagtypes.id
+ WHERE flags.status = '+'
+ ORDER BY flags.modification_date");
+ my $count = 1;
+ my $total = scalar @$ra;
+ my %user_seen;
+ foreach my $ra_row (@$ra) {
+ my ($user_id, $attach_id, $flag_name) = @$ra_row;
+ next if $user_seen{$user_id};
+ my $found_flag = 0;
+ foreach my $flag_re (FLAG_REGEXES) {
+ $found_flag = 1 if ($flag_name =~ $flag_re);
+ }
+ next if !$found_flag;
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ $sth->execute($attach_id, $user_id);
+ $user_seen{$user_id} = 1;
+ }
+
+ print "done\n";
+}
+
+sub object_columns {
+ my ($self, $args) = @_;
+ my ($class, $columns) = @$args{qw(class columns)};
+ if ($class->isa('Bugzilla::User')) {
+ push(@$columns, 'first_patch_approved_id');
+ }
+}
+
+sub flag_end_of_update {
+ my ($self, $args) = @_;
+ my ($object, $timestamp, $new_flags) = @$args{qw(object timestamp new_flags)};
+
+ if ($object->isa('Bugzilla::Attachment')
+ && @$new_flags
+ && grep($_ eq $object->bug->product, ENABLED_PRODUCTS)
+ && !$object->attacher->first_patch_approved_id)
+ {
+ my $attachment = $object;
+
+ # Glob: Borrowed this code from your push extension :)
+ foreach my $change (@$new_flags) {
+ $change =~ s/^[^:]+://; # get rid of setter
+ $change =~ s/\([^\)]+\)$//; # get rid of requestee
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+
+ # Only interested in flags set to +
+ next if $value ne '+';
+
+ my $found_flag = 0;
+ foreach my $flag_re (FLAG_REGEXES) {
+ $found_flag = 1 if ($name =~ $flag_re);
+ }
+ next if !$found_flag;
+
+ _send_approval_mail($attachment, $timestamp);
+
+ last;
+ }
+ }
+}
+
+sub _send_approval_mail {
+ my ($attachment, $timestamp) = @_;
+
+ my $vars = {
+ date => format_time($timestamp, '%a, %d %b %Y %T %z', 'UTC'),
+ to_user => $attachment->attacher->email,
+ from_user => EMAIL_FROM,
+ };
+
+ my $msg;
+ my $template = Bugzilla->template_inner($attachment->attacher->setting('lang'));
+ $template->process("contributor/email.txt.tmpl", $vars, \$msg)
+ || ThrowTemplateError($template->error());
+
+ MessageToMTA($msg);
+
+ # Make sure we don't do this again
+ Bugzilla->dbh->do("UPDATE profiles SET first_patch_approved_id = ? WHERE userid = ?",
+ undef, $attachment->id, $attachment->attacher->id);
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/ContributorEngagement/lib/Constants.pm b/extensions/ContributorEngagement/lib/Constants.pm
new file mode 100644
index 000000000..851c0dbc2
--- /dev/null
+++ b/extensions/ContributorEngagement/lib/Constants.pm
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ContributorEngagement::Constants;
+
+use strict;
+
+use base qw(Exporter);
+
+our @EXPORT = qw(
+ EMAIL_FROM
+ ENABLED_PRODUCTS
+ FLAG_REGEXES
+);
+
+use constant EMAIL_FROM => 'bugzilla-daemon@mozilla.org';
+
+use constant ENABLED_PRODUCTS => (
+ "Core",
+ "Firefox for Android",
+ "Firefox",
+ "Testing",
+ "Toolkit",
+ "Mozilla Services",
+ "TestProduct",
+);
+
+use constant FLAG_REGEXES => (
+ qr/^approval/
+);
+
+1;
diff --git a/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl b/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl
new file mode 100644
index 000000000..b403a4bfb
--- /dev/null
+++ b/extensions/ContributorEngagement/template/en/default/contributor/email.txt.tmpl
@@ -0,0 +1,46 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+[% PROCESS "global/variables.none.tmpl" %]
+From: [% from_user FILTER none %]
+To: [% to_user FILTER none %]
+Subject: Congratulations on having your first patch approved
+Date: [% date FILTER none %]
+
+Congratulations on having your first patch approved, and thank you
+for your contribution to Mozilla.
+
+The next step is to get the patch actually checked in to our repository.
+For more information about how to make that happen, check out this post:
+
+https://developer.mozilla.org/en/Creating_a_patch_that_can_be_checked_in
+
+While you are going through those final steps, if you're looking for a
+new project to take on, have a look at our list of 'mentored' [% terms.bugs %] ([% terms.bugs %] where
+someone is specifically available to help you):
+
+https://bugzil.la/sw:mentor
+
+Alternatively, you could join us on our IRC chat server in the #introduction
+channel and ask for suggestions about what would be a good [% terms.bugs %] to work on.
+There's more about using our chat server at:
+
+http://irc.mozilla.org/
+
+If you haven't done so already, this is also a good time to sign up to the
+Mozilla Contributor Directory and create a profile for yourself. Doing this
+will give you access to community members' profiles so you can reach out and
+connect with other Mozillians. You will need someone to 'vouch for' your
+profile; if you don't know any other Mozillians well, why not contact the
+person who approved your patch?
+
+The directory is here:
+
+https://mozillians.org/
+
+Thanks again for your help :-)
+Josh, Kyle, Dietrich and Brian; Coding Stewards
diff --git a/extensions/Example/Extension.pm b/extensions/Example/Extension.pm
index c0b3c6210..fe29beb0b 100644
--- a/extensions/Example/Extension.pm
+++ b/extensions/Example/Extension.pm
@@ -44,6 +44,20 @@ use constant REL_EXAMPLE => -127;
our $VERSION = '1.0';
+sub admin_editusers_action {
+ my ($self, $args) = @_;
+ my ($vars, $action, $user) = @$args{qw(vars action user)};
+ my $template = Bugzilla->template;
+
+ if ($action eq 'my_action') {
+ # Allow to restrict the search to any group the user is allowed to bless.
+ $vars->{'restrictablegroups'} = $user->bless_groups();
+ $template->process('admin/users/search.html.tmpl', $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+}
+
sub attachment_process_data {
my ($self, $args) = @_;
my $type = $args->{attributes}->{mimetype};
@@ -80,6 +94,44 @@ sub auth_verify_methods {
}
}
+sub bug_check_can_change_field {
+ my ($self, $args) = @_;
+
+ my ($bug, $field, $new_value, $old_value, $priv_results)
+ = @$args{qw(bug field new_value old_value priv_results)};
+
+ my $user = Bugzilla->user;
+
+ # Disallow a bug from being reopened if currently closed unless user
+ # is in 'admin' group
+ if ($field eq 'bug_status' && $bug->product_obj->name eq 'Example') {
+ if (!is_open_state($old_value) && is_open_state($new_value)
+ && !$user->in_group('admin'))
+ {
+ push(@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ return;
+ }
+ }
+
+ # Disallow a bug's keywords from being edited unless user is the
+ # reporter of the bug
+ if ($field eq 'keywords' && $bug->product_obj->name eq 'Example'
+ && $user->login ne $bug->reporter->login)
+ {
+ push(@$priv_results, PRIVILEGES_REQUIRED_REPORTER);
+ return;
+ }
+
+ # Allow updating of priority even if user cannot normally edit the bug
+ # and they are in group 'engineering'
+ if ($field eq 'priority' && $bug->product_obj->name eq 'Example'
+ && $user->in_group('engineering'))
+ {
+ push(@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ return;
+ }
+}
+
sub bug_columns {
my ($self, $args) = @_;
my $columns = $args->{'columns'};
@@ -116,6 +168,42 @@ sub bug_end_of_create_validators {
# $bug_params->{cc} = [];
}
+sub bug_start_of_update {
+ my ($self, $args) = @_;
+
+ # This code doesn't actually *do* anything, it's just here to show you
+ # how to use this hook.
+ my ($bug, $old_bug, $timestamp, $changes) =
+ @$args{qw(bug old_bug timestamp changes)};
+
+ foreach my $field (keys %$changes) {
+ my $used_to_be = $changes->{$field}->[0];
+ my $now_it_is = $changes->{$field}->[1];
+ }
+
+ my $old_summary = $old_bug->short_desc;
+
+ my $status_message;
+ if (my $status_change = $changes->{'bug_status'}) {
+ my $old_status = new Bugzilla::Status({ name => $status_change->[0] });
+ my $new_status = new Bugzilla::Status({ name => $status_change->[1] });
+ if ($new_status->is_open && !$old_status->is_open) {
+ $status_message = "Bug re-opened!";
+ }
+ if (!$new_status->is_open && $old_status->is_open) {
+ $status_message = "Bug closed!";
+ }
+ }
+
+ my $bug_id = $bug->id;
+ my $num_changes = scalar keys %$changes;
+ my $result = "There were $num_changes changes to fields on bug $bug_id"
+ . " at $timestamp.";
+ # Uncomment this line to see $result in your webserver's error log whenever
+ # you update a bug.
+ # warn $result;
+}
+
sub bug_end_of_update {
my ($self, $args) = @_;
@@ -678,10 +766,12 @@ sub _check_short_desc {
my $invocant = shift;
my $value = $invocant->$original(@_);
if ($value !~ /example/i) {
- # Uncomment this line to make Bugzilla throw an error every time
+ # Use this line to make Bugzilla throw an error every time
# you try to file a bug or update a bug without the word "example"
# in the summary.
- #ThrowUserError('example_short_desc_invalid');
+ if (0) {
+ ThrowUserError('example_short_desc_invalid');
+ }
}
return $value;
}
@@ -697,6 +787,12 @@ sub page_before_template {
}
}
+sub path_info_whitelist {
+ my ($self, $args) = @_;
+ my $whitelist = $args->{whitelist};
+ push(@$whitelist, "page.cgi");
+}
+
sub post_bug_after_creation {
my ($self, $args) = @_;
@@ -825,58 +921,6 @@ sub template_before_process {
}
}
-sub bug_check_can_change_field {
- my ($self, $args) = @_;
-
- my ($bug, $field, $new_value, $old_value, $priv_results)
- = @$args{qw(bug field new_value old_value priv_results)};
-
- my $user = Bugzilla->user;
-
- # Disallow a bug from being reopened if currently closed unless user
- # is in 'admin' group
- if ($field eq 'bug_status' && $bug->product_obj->name eq 'Example') {
- if (!is_open_state($old_value) && is_open_state($new_value)
- && !$user->in_group('admin'))
- {
- push(@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
- return;
- }
- }
-
- # Disallow a bug's keywords from being edited unless user is the
- # reporter of the bug
- if ($field eq 'keywords' && $bug->product_obj->name eq 'Example'
- && $user->login ne $bug->reporter->login)
- {
- push(@$priv_results, PRIVILEGES_REQUIRED_REPORTER);
- return;
- }
-
- # Allow updating of priority even if user cannot normally edit the bug
- # and they are in group 'engineering'
- if ($field eq 'priority' && $bug->product_obj->name eq 'Example'
- && $user->in_group('engineering'))
- {
- push(@$priv_results, PRIVILEGES_REQUIRED_NONE);
- return;
- }
-}
-
-sub admin_editusers_action {
- my ($self, $args) = @_;
- my ($vars, $action, $user) = @$args{qw(vars action user)};
- my $template = Bugzilla->template;
-
- if ($action eq 'my_action') {
- # Allow to restrict the search to any group the user is allowed to bless.
- $vars->{'restrictablegroups'} = $user->bless_groups();
- $template->process('admin/users/search.html.tmpl', $vars)
- || ThrowTemplateError($template->error());
- exit;
- }
-}
-
sub user_preferences {
my ($self, $args) = @_;
my $tab = $args->{current_tab};
diff --git a/extensions/FlagDefaultRequestee/Config.pm b/extensions/FlagDefaultRequestee/Config.pm
new file mode 100644
index 000000000..70c5ca33a
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/Config.pm
@@ -0,0 +1,17 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::FlagDefaultRequestee;
+
+use strict;
+
+use constant NAME => 'FlagDefaultRequestee';
+
+use constant REQUIRED_MODULES => [];
+use constant OPTIONAL_MODULES => [];
+
+__PACKAGE__->NAME;
diff --git a/extensions/FlagDefaultRequestee/Extension.pm b/extensions/FlagDefaultRequestee/Extension.pm
new file mode 100644
index 000000000..b444bce49
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/Extension.pm
@@ -0,0 +1,144 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::FlagDefaultRequestee;
+
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::FlagType;
+use Bugzilla::User;
+
+use Bugzilla::Extension::FlagDefaultRequestee::Constants;
+
+our $VERSION = '1';
+
+################
+# Installation #
+################
+
+sub install_update_db {
+ my $dbh = Bugzilla->dbh;
+ if (!$dbh->bz_column_info('flagtypes', 'default_requestee')) {
+ $dbh->bz_add_column('flagtypes', 'default_requestee', {
+ TYPE => 'INT3', NOTNULL => 0,
+ REFERENCES => { TABLE => 'profiles',
+ COLUMN => 'userid',
+ DELETE => 'SET NULL' }
+ });
+ }
+}
+
+#############
+# Templates #
+#############
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my ($vars, $file) = @$args{qw(vars file)};
+ my $dbh = Bugzilla->dbh;
+
+ return unless Bugzilla->user->id;
+
+ return unless grep { $_ eq $file } FLAGTYPE_TEMPLATES;
+
+ my $flag_types = [];
+ if (exists $vars->{bug} || exists $vars->{attachment}) {
+ my $bug;
+ if (exists $vars->{bug}) {
+ $bug = $vars->{'bug'};
+ } elsif (exists $vars->{'attachment'}) {
+ $bug = $vars->{'attachment'}->{bug};
+ }
+
+ $flag_types = Bugzilla::FlagType::match({
+ 'target_type' => ($file =~ /^bug/ ? 'bug' : 'attachment'),
+ 'product_id' => $bug->product_id,
+ 'component_id' => $bug->component_id,
+ 'bug_id' => $bug->id,
+ 'active_or_has_flags' => $bug->id,
+ });
+
+ $vars->{flag_currently_requested} ||= {};
+ foreach my $type (@$flag_types) {
+ my $flags = Bugzilla::Flag->match({
+ type_id => $type->id,
+ bug_id => $bug->id,
+ status => '?'
+ });
+ map { $vars->{flag_currently_requested}->{$_->id} = 1 } @$flags;
+ }
+ }
+ elsif ($file =~ /^bug\/create/ && exists $vars->{product}) {
+ my $bug_flags = $vars->{product}->flag_types->{bug};
+ my $attachment_flags = $vars->{product}->flag_types->{attachment};
+ $flag_types = [ map { $_ } (@$bug_flags, @$attachment_flags) ];
+ }
+
+ return if !@$flag_types;
+
+ $vars->{flag_default_requestees} ||= {};
+ foreach my $type (@$flag_types) {
+ next if !$type->default_requestee;
+ $vars->{flag_default_requestees}->{$type->id} = $type->default_requestee->login;
+ }
+}
+
+#########
+# Admin #
+#########
+
+sub flagtype_end_of_create {
+ my ($self, $args) = @_;
+ _set_default_requestee($args->{id});
+}
+
+sub flagtype_end_of_update {
+ my ($self, $args) = @_;
+ _set_default_requestee($args->{id});
+}
+
+sub _set_default_requestee {
+ my $type_id = shift;
+ my $input = Bugzilla->input_params;
+ my $dbh = Bugzilla->dbh;
+
+ my $requestee_login = $input->{'default_requestee'};
+
+ my $requestee_id = undef;
+ if ($requestee_login) {
+ my $requestee = Bugzilla::User->check($requestee_login);
+ $requestee_id = $requestee->id;
+ }
+
+ $dbh->do("UPDATE flagtypes SET default_requestee = ? WHERE id = ?",
+ undef, $requestee_id, $type_id);
+}
+
+##################
+# Object Methods #
+##################
+
+BEGIN {
+ *Bugzilla::FlagType::default_requestee = \&_default_requestee;
+}
+
+sub _default_requestee {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $self->{default_requestee} if exists $self->{default_requestee};
+ my $requestee_id = $dbh->selectrow_array("SELECT default_requestee
+ FROM flagtypes
+ WHERE id = ?",
+ undef, $self->id);
+ $self->{default_requestee} = $requestee_id
+ ? Bugzilla::User->new($requestee_id)
+ : undef;
+ return $self->{default_requestee};
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/FlagDefaultRequestee/lib/Constants.pm b/extensions/FlagDefaultRequestee/lib/Constants.pm
new file mode 100644
index 000000000..467028423
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/lib/Constants.pm
@@ -0,0 +1,25 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::FlagDefaultRequestee::Constants;
+
+use strict;
+
+use base qw(Exporter);
+
+our @EXPORT = qw(
+ FLAGTYPE_TEMPLATES
+);
+
+use constant FLAGTYPE_TEMPLATES => (
+ "attachment/edit.html.tmpl",
+ "attachment/createformcontents.html.tmpl",
+ "bug/edit.html.tmpl",
+ "bug/create/create.html.tmpl"
+);
+
+1;
diff --git a/extensions/FlagDefaultRequestee/template/en/default/flag/default_requestees.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/flag/default_requestees.html.tmpl
new file mode 100644
index 000000000..db728c168
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/flag/default_requestees.html.tmpl
@@ -0,0 +1,105 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF flag_default_requestees.keys.size %]
+ <script type="text/javascript">
+ var currently_requested = new Array();
+ var default_requestees = new Array();
+ [% FOREACH id = flag_currently_requested.keys %]
+ currently_requested.push('[% id FILTER js %]');
+ [% END %]
+ [% FOREACH id = flag_default_requestees.keys %]
+ default_requestees['id_[% id FILTER js %]'] = '[% flag_default_requestees.$id FILTER js %]';
+ [% END %]
+
+ function fdrSetDefaultRequestee(field, default_requestee) {
+ field.value = default_requestee;
+ field.focus();
+ field.select();
+ }
+
+ function fdrOnChange(ev) {
+ var parts = ev.target.id.split('-');
+ var flag = parts[0];
+ var id = parts[1];
+ var state = ev.target.value;
+ var requestee_field;
+
+ if (flag.search(/_type/) == -1) {
+ for (var i = 0; i < currently_requested.length; i++) {
+ if (id == currently_requested[i]) {
+ return;
+ }
+ }
+ requestee_field = YAHOO.util.Dom.get('requestee-' + id);
+ parts = ev.target.className.split('-');
+ id = parts[1];
+ }
+ else {
+ requestee_field = YAHOO.util.Dom.get('requestee_type-' + id);
+ }
+ if (!requestee_field) return;
+
+ var current_requestee = requestee_field.value;
+ var default_requestee = default_requestees['id_' + id];
+ if (!default_requestee) return;
+
+ if (state == '?' && !current_requestee && default_requestee) {
+ fdrSetDefaultRequestee(requestee_field, default_requestees['id_' + id]);
+ }
+ else if (state == '?' && current_requestee != default_requestee) {
+ fdrShowDefaultLink(requestee_field, id);
+ }
+ }
+
+ YAHOO.util.Event.onDOMReady(function() {
+ var selects = YAHOO.util.Dom.getElementsByClassName('flag_select');
+ for (var i = 0; i < selects.length; i++) {
+ YAHOO.util.Event.on(selects[i], 'change', fdrOnChange);
+ }
+
+ for (var i = 0; i < currently_requested.length; i++) {
+ var flag_id = currently_requested[i];
+ var flag_field = YAHOO.util.Dom.get('flag-' + flag_id);
+ var requestee_field = YAHOO.util.Dom.get('requestee-' + flag_id);
+ if (!requestee_field) continue;
+ var parts = flag_field.className.split('-');
+ var type_id = parts[1];
+ var current_requestee = requestee_field.value;
+ var default_requestee = default_requestees['id_' + type_id];
+ if (!default_requestee) continue;
+ if (current_requestee != default_requestee) {
+ fdrShowDefaultLink(requestee_field, type_id, flag_id);
+ }
+ }
+ });
+
+ function fdrHideDefaultLink (flag_id) {
+ YAHOO.util.Dom.addClass('default_requestee_' + flag_id, 'bz_default_hidden');
+ }
+
+ function fdrShowDefaultLink (requestee_field, type_id, flag_id) {
+ var default_requestee = default_requestees['id_' + type_id];
+
+ var default_link = document.createElement('a');
+ YAHOO.util.Dom.setAttribute(default_link, 'href', 'javascript:void(0)');
+ default_link.appendChild(document.createTextNode('default requestee'));
+ YAHOO.util.Event.addListener(default_link, 'click', function() {
+ fdrSetDefaultRequestee(requestee_field, default_requestee);
+ fdrHideDefaultLink(flag_id);
+ });
+
+ var default_span = document.createElement('span');
+ YAHOO.util.Dom.setAttribute(default_span, 'id', 'default_requestee_' + flag_id);
+ default_span.appendChild(document.createTextNode("\u00a0("));
+ default_span.appendChild(default_link);
+ default_span.appendChild(document.createTextNode(')'));
+ requestee_field.parentNode.parentNode.appendChild(default_span);
+ }
+ </script>
+[% END %]
diff --git a/extensions/FlagDefaultRequestee/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl
new file mode 100644
index 000000000..edefca370
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl
@@ -0,0 +1,21 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<tr>
+ <th>Default Requestee:</th>
+ <td>
+ If flag is specifically requestable, this user will be entered in the
+ requestee field by default unless the user changes it.<br>
+ [% INCLUDE global/userselect.html.tmpl
+ name => 'default_requestee'
+ id => 'default_requestee'
+ value => type.default_requestee.login
+ classes => ['requestee']
+ %]
+ </td>
+</tr>
diff --git a/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/create-end.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/create-end.html.tmpl
new file mode 100644
index 000000000..20b2526d0
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/create-end.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE flag/default_requestees.html.tmpl %]
diff --git a/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/edit-end.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/edit-end.html.tmpl
new file mode 100644
index 000000000..20b2526d0
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/hook/attachment/edit-end.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE flag/default_requestees.html.tmpl %]
diff --git a/extensions/FlagDefaultRequestee/template/en/default/hook/bug/create/create-form.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/hook/bug/create/create-form.html.tmpl
new file mode 100644
index 000000000..20b2526d0
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/hook/bug/create/create-form.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE flag/default_requestees.html.tmpl %]
diff --git a/extensions/FlagDefaultRequestee/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/FlagDefaultRequestee/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..20b2526d0
--- /dev/null
+++ b/extensions/FlagDefaultRequestee/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE flag/default_requestees.html.tmpl %]
diff --git a/extensions/FlagTypeComment/Config.pm b/extensions/FlagTypeComment/Config.pm
new file mode 100644
index 000000000..e20be10e3
--- /dev/null
+++ b/extensions/FlagTypeComment/Config.pm
@@ -0,0 +1,29 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the FlagTypeComment Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Alex Keybl
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Alex Keybl <akeybl@mozilla.com>
+# byron jones <glob@mozilla.com>
+
+package Bugzilla::Extension::FlagTypeComment;
+use strict;
+
+use constant NAME => 'FlagTypeComment';
+
+use constant REQUIRED_MODULES => [];
+use constant OPTIONAL_MODULES => [];
+
+__PACKAGE__->NAME;
diff --git a/extensions/FlagTypeComment/Extension.pm b/extensions/FlagTypeComment/Extension.pm
new file mode 100644
index 000000000..8da6101ad
--- /dev/null
+++ b/extensions/FlagTypeComment/Extension.pm
@@ -0,0 +1,200 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the FlagTypeComment Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Alex Keybl
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Alex Keybl <akeybl@mozilla.com>
+# byron jones <glob@mozilla.com>
+
+package Bugzilla::Extension::FlagTypeComment;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Extension::FlagTypeComment::Constants;
+
+use Bugzilla::FlagType;
+use Bugzilla::Util qw(trick_taint);
+use Scalar::Util qw(blessed);
+
+our $VERSION = '1';
+
+################
+# Installation #
+################
+
+sub db_schema_abstract_schema {
+ my ($self, $args) = @_;
+ $args->{'schema'}->{'flagtype_comments'} = {
+ FIELDS => [
+ type_id => {
+ TYPE => 'SMALLINT(6)',
+ NOTNULL => 1,
+ REFERENCES => {
+ TABLE => 'flagtypes',
+ COLUMN => 'id',
+ DELETE => 'CASCADE'
+ }
+ },
+ on_status => {
+ TYPE => 'CHAR(1)',
+ NOTNULL => 1
+ },
+ comment => {
+ TYPE => 'MEDIUMTEXT',
+ NOTNULL => 1
+ },
+ ],
+ INDEXES => [
+ flagtype_comments_idx => ['type_id'],
+ ],
+ };
+}
+
+#############
+# Templates #
+#############
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my ($vars, $file) = @$args{qw(vars file)};
+
+ return unless Bugzilla->user->id;
+ if (grep { $_ eq $file } FLAGTYPE_COMMENT_TEMPLATES) {
+ _set_ftc_states($file, $vars);
+ }
+}
+
+sub _set_ftc_states {
+ my ($file, $vars) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $ftc_flags;
+ my $db_result;
+ if ($file =~ /^admin\//) {
+ # admin
+ my $type = $vars->{'type'} || return;
+ my ($target_type, $id);
+ if (blessed($type)) {
+ ($target_type, $id) = ($type->target_type, $type->id);
+ } else {
+ ($target_type, $id) = ($type->{target_type}, $type->{id});
+ trick_taint($id) if $id;
+ }
+ if ($target_type eq 'bug') {
+ return unless FLAGTYPE_COMMENT_BUG_FLAGS;
+ } else {
+ return unless FLAGTYPE_COMMENT_ATTACHMENT_FLAGS;
+ }
+ if ($id) {
+ $db_result = $dbh->selectall_arrayref(
+ "SELECT type_id AS flagtype, on_status AS state, comment AS text
+ FROM flagtype_comments
+ WHERE type_id = ?",
+ { Slice => {} }, $id);
+ }
+ } else {
+ # creating/editing attachment / viewing bug
+ my $bug;
+ if (exists $vars->{'bug'}) {
+ $bug = $vars->{'bug'};
+ } elsif (exists $vars->{'attachment'}) {
+ $bug = $vars->{'attachment'}->{bug};
+ } else {
+ return;
+ }
+
+ my $flag_types = Bugzilla::FlagType::match({
+ 'target_type' => ($file =~ /^bug/ ? 'bug' : 'attachment'),
+ 'product_id' => $bug->product_id,
+ 'component_id' => $bug->component_id,
+ 'bug_id' => $bug->id,
+ 'active_or_has_flags' => $bug->id,
+ });
+
+ my $types = join(',', map { $_->id } @$flag_types);
+ my $states = "'" . join("','", FLAGTYPE_COMMENT_STATES) . "'";
+ $db_result = $dbh->selectall_arrayref(
+ "SELECT type_id AS flagtype, on_status AS state, comment AS text
+ FROM flagtype_comments
+ WHERE type_id IN ($types) AND on_status IN ($states)",
+ { Slice => {} });
+ }
+
+ foreach my $row (@$db_result) {
+ $ftc_flags->{$row->{'flagtype'}} ||= {};
+ $ftc_flags->{$row->{'flagtype'}}{$row->{'state'}} = $row->{text};
+ }
+
+ $vars->{'ftc_states'} = [ FLAGTYPE_COMMENT_STATES ];
+ $vars->{'ftc_flags'} = $ftc_flags;
+}
+
+#########
+# Admin #
+#########
+
+sub flagtype_end_of_create {
+ my ($self, $args) = @_;
+ _set_flagtypes($args->{type});
+}
+
+sub flagtype_end_of_update {
+ my ($self, $args) = @_;
+ _set_flagtypes($args->{type});
+}
+
+sub _set_flagtypes {
+ my $flag_type = shift;
+ my $flagtype_id = $flag_type->id;
+ my $input = Bugzilla->input_params;
+ my $dbh = Bugzilla->dbh;
+
+ foreach my $state (FLAGTYPE_COMMENT_STATES) {
+ next if (!defined $input->{"ftc_${flagtype_id}_$state"}
+ && !defined $input->{"ftc_new_$state"});
+
+ my $text = $input->{"ftc_${flagtype_id}_$state"} || $input->{"ftc_new_$state"} || '';
+ $text =~ s/\r\n/\n/g;
+ trick_taint($text);
+
+ if ($text ne '') {
+ if ($dbh->selectrow_array(
+ "SELECT 1 FROM flagtype_comments WHERE type_id=? AND on_status=?",
+ undef,
+ $flagtype_id, $state)
+ ) {
+ $dbh->do(
+ "UPDATE flagtype_comments SET comment=?
+ WHERE type_id=? AND on_status=?",
+ undef,
+ $text, $flagtype_id, $state);
+ } else {
+ $dbh->do(
+ "INSERT INTO flagtype_comments(type_id, on_status, comment)
+ VALUES (?, ?, ?)",
+ undef,
+ $flagtype_id, $state, $text);
+ }
+
+ } else {
+ $dbh->do(
+ "DELETE FROM flagtype_comments WHERE type_id=? AND on_status=?",
+ undef,
+ $flagtype_id, $state);
+ }
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/FlagTypeComment/lib/Constants.pm b/extensions/FlagTypeComment/lib/Constants.pm
new file mode 100644
index 000000000..e1a99e5b3
--- /dev/null
+++ b/extensions/FlagTypeComment/lib/Constants.pm
@@ -0,0 +1,50 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the FlagTypeComment Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Alex Keybl
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Alex Keybl <akeybl@mozilla.com>
+# byron jones <glob@mozilla.com>
+
+package Bugzilla::Extension::FlagTypeComment::Constants;
+use strict;
+
+use base qw(Exporter);
+our @EXPORT = qw(
+ FLAGTYPE_COMMENT_TEMPLATES
+ FLAGTYPE_COMMENT_STATES
+ FLAGTYPE_COMMENT_BUG_FLAGS
+ FLAGTYPE_COMMENT_ATTACHMENT_FLAGS
+);
+
+use constant FLAGTYPE_COMMENT_STATES => ("?", "+", "-");
+use constant FLAGTYPE_COMMENT_BUG_FLAGS => 0;
+use constant FLAGTYPE_COMMENT_ATTACHMENT_FLAGS => 1;
+
+sub FLAGTYPE_COMMENT_TEMPLATES {
+ my @result = ("admin/flag-type/edit.html.tmpl");
+ if (FLAGTYPE_COMMENT_BUG_FLAGS) {
+ push @result, ("bug/comments.html.tmpl");
+ }
+ if (FLAGTYPE_COMMENT_ATTACHMENT_FLAGS) {
+ push @result, (
+ "attachment/edit.html.tmpl",
+ "attachment/createformcontents.html.tmpl",
+ );
+ }
+ return @result;
+}
+
+1;
diff --git a/extensions/FlagTypeComment/template/en/default/flag/type_comment.html.tmpl b/extensions/FlagTypeComment/template/en/default/flag/type_comment.html.tmpl
new file mode 100644
index 000000000..95c0cb283
--- /dev/null
+++ b/extensions/FlagTypeComment/template/en/default/flag/type_comment.html.tmpl
@@ -0,0 +1,54 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is FlagTypeComment Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Alex Keybl <akeybl@mozilla.com>
+ # byron jones <glob@mozilla.com>
+ #%]
+
+[% IF ftc_flags.keys.size %]
+ <script type="text/javascript">
+ YAHOO.util.Event.onDOMReady(function() {
+ var selects = YAHOO.util.Dom.getElementsByClassName('flag_select');
+ for (var i = 0; i < selects.length; i++) {
+ YAHOO.util.Event.on(selects[i], 'change', ftc_on_change);
+ }
+ });
+
+ function ftc_on_change(ev) {
+ var id = ev.target.id.split('-')[1];
+ var state = ev.target.value;
+ var commentEl = document.getElementById('comment');
+ if (!commentEl) return;
+ [% FOREACH type_id = ftc_flags.keys %]
+ [% FOREACH state = ftc_states %]
+ if ([% type_id FILTER none %] == id && '[% state FILTER js %]' == state) {
+ var text = '[% ftc_flags.$type_id.$state FILTER js %]';
+ var value = commentEl.value;
+ if (value == text) {
+ return;
+ } else if (value == '') {
+ commentEl.value = text;
+ } else {
+ commentEl.value = text + "\n\n" + value;
+ }
+ }
+ [% END %]
+ [% END %]
+ }
+ </script>
+[% END %]
diff --git a/extensions/FlagTypeComment/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl b/extensions/FlagTypeComment/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl
new file mode 100644
index 000000000..3ca5e8aa7
--- /dev/null
+++ b/extensions/FlagTypeComment/template/en/default/hook/admin/flag-type/edit-rows.html.tmpl
@@ -0,0 +1,45 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is FlagTypeComment Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Alex Keybl <akeybl@mozilla.com>
+ # byron jones <glob@mozilla.com>
+ #%]
+
+[% IF ftc_states %]
+ <tr>
+ <th>Flag Comments:</th>
+ <td>add text into the comment box when flag is changed to a state</td>
+ </tr>
+
+ [% FOREACH state = ftc_states %]
+ [% ftc_type_id = "ftc_${type.id}_$state" %]
+ [% IF action == 'insert' %]
+ [% ftc_type_id = "ftc_new_$state" %]
+ [% END %]
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ for [% state FILTER html %]<br>
+ <textarea
+ id="[% ftc_type_id FILTER html %]"
+ name="[% ftc_type_id FILTER html %]"
+ cols="50" rows="2">[% ftc_flags.${type.id}.$state FILTER html %]</textarea>
+ </td>
+ </tr>
+ [% END %]
+[% END %]
diff --git a/extensions/FlagTypeComment/template/en/default/hook/attachment/create-end.html.tmpl b/extensions/FlagTypeComment/template/en/default/hook/attachment/create-end.html.tmpl
new file mode 100644
index 000000000..dfa010d7c
--- /dev/null
+++ b/extensions/FlagTypeComment/template/en/default/hook/attachment/create-end.html.tmpl
@@ -0,0 +1,23 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is FlagTypeComment Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Alex Keybl <akeybl@mozilla.com>
+ # byron jones <glob@mozilla.com>
+ #%]
+
+[% INCLUDE flag/type_comment.html.tmpl %]
diff --git a/extensions/FlagTypeComment/template/en/default/hook/attachment/edit-end.html.tmpl b/extensions/FlagTypeComment/template/en/default/hook/attachment/edit-end.html.tmpl
new file mode 100644
index 000000000..dfa010d7c
--- /dev/null
+++ b/extensions/FlagTypeComment/template/en/default/hook/attachment/edit-end.html.tmpl
@@ -0,0 +1,23 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is FlagTypeComment Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Alex Keybl <akeybl@mozilla.com>
+ # byron jones <glob@mozilla.com>
+ #%]
+
+[% INCLUDE flag/type_comment.html.tmpl %]
diff --git a/extensions/FlagTypeComment/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/FlagTypeComment/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..dfa010d7c
--- /dev/null
+++ b/extensions/FlagTypeComment/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,23 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is FlagTypeComment Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Alex Keybl <akeybl@mozilla.com>
+ # byron jones <glob@mozilla.com>
+ #%]
+
+[% INCLUDE flag/type_comment.html.tmpl %]
diff --git a/extensions/GuidedBugEntry/Config.pm b/extensions/GuidedBugEntry/Config.pm
new file mode 100644
index 000000000..e4bc9c70b
--- /dev/null
+++ b/extensions/GuidedBugEntry/Config.pm
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::GuidedBugEntry;
+use strict;
+
+use constant NAME => 'GuidedBugEntry';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/GuidedBugEntry/Extension.pm b/extensions/GuidedBugEntry/Extension.pm
new file mode 100644
index 000000000..5665e18ae
--- /dev/null
+++ b/extensions/GuidedBugEntry/Extension.pm
@@ -0,0 +1,116 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::GuidedBugEntry;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Token;
+use Bugzilla::Error;
+use Bugzilla::Status;
+use Bugzilla::Util 'url_quote';
+use Bugzilla::UserAgent;
+
+our $VERSION = '1';
+
+sub enter_bug_start {
+ my ($self, $args) = @_;
+ my $vars = $args->{vars};
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+ my $user = Bugzilla->user;
+
+ # hack for skipping old guided code when enabled
+ $vars->{'disable_guided'} = 1;
+
+ # force guided format for new users
+ my $format = $cgi->param('format') || '';
+ if (
+ $format eq 'guided' ||
+ (
+ $format eq '' &&
+ !$user->in_group('canconfirm')
+ )
+ ) {
+ # skip the first step if a product is provided
+ if ($cgi->param('product')) {
+ print $cgi->redirect('enter_bug.cgi?format=guided#h=dupes' .
+ '|' . url_quote($cgi->param('product')) .
+ '|' . url_quote($cgi->param('component') || '')
+ );
+ exit;
+ }
+
+ $self->_init_vars($vars);
+ print $cgi->header();
+ $template->process('guided/guided.html.tmpl', $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+
+ # we use the __default__ format to bypass the guided entry
+ # it isn't understood upstream, so remove it once a product
+ # has been selected.
+ if (
+ ($cgi->param('format') && $cgi->param('format') eq "__default__")
+ && ($cgi->param('product') && $cgi->param('product') ne '')
+ ) {
+ $cgi->delete('format');
+ }
+}
+
+sub _init_vars {
+ my ($self, $vars) = @_;
+ my $user = Bugzilla->user;
+
+ my @enterable_products = @{$user->get_enterable_products};
+ ThrowUserError('no_products') unless scalar(@enterable_products);
+
+ my @classifications = ({object => undef, products => \@enterable_products});
+
+ my $class;
+ foreach my $product (@enterable_products) {
+ $class->{$product->classification_id}->{'object'} ||=
+ new Bugzilla::Classification($product->classification_id);
+ push(@{$class->{$product->classification_id}->{'products'}}, $product);
+ }
+ @classifications =
+ sort {
+ $a->{'object'}->sortkey <=> $b->{'object'}->sortkey
+ || lc($a->{'object'}->name) cmp lc($b->{'object'}->name)
+ } (values %$class);
+ $vars->{'classifications'} = \@classifications;
+
+ my @open_states = BUG_STATE_OPEN();
+ $vars->{'open_states'} = \@open_states;
+
+ $vars->{'token'} = issue_session_token('create_bug');
+
+ $vars->{'platform'} = detect_platform();
+ $vars->{'op_sys'} = detect_op_sys();
+
+ eval 'use Bugzilla::Extension::BMO::Data';
+ $vars->{'BMO'} = $@ ? 0 : 1;
+}
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ return unless $page eq 'guided_products.js';
+
+ # import product -> security group mappings from the BMO ext
+
+ our %product_sec_groups;
+ eval q#use Bugzilla::Extension::BMO::Data '%product_sec_groups'#;
+ return if $@;
+
+ $vars->{'products'} = \%product_sec_groups;
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/GuidedBugEntry/template/en/default/bug/create/comment-guided.txt.tmpl b/extensions/GuidedBugEntry/template/en/default/bug/create/comment-guided.txt.tmpl
new file mode 100644
index 000000000..6b0de9466
--- /dev/null
+++ b/extensions/GuidedBugEntry/template/en/default/bug/create/comment-guided.txt.tmpl
@@ -0,0 +1,25 @@
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+User Agent: [% cgi.param('user_agent') %]
+[% IF cgi.param('build_id') %]
+Build ID: [% cgi.param('build_id') %][% END %]
+
+[% IF cgi.param('bug_steps') %]
+Steps to reproduce:
+
+[%+ cgi.param('bug_steps') %]
+[% END %]
+
+[% IF cgi.param('actual') %]
+
+Actual results:
+
+[%+ cgi.param('actual') %]
+[% END %]
+
+[% IF cgi.param('expected') %]
+
+Expected results:
+
+[%+ cgi.param('expected') %]
+[% END %]
diff --git a/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl
new file mode 100644
index 000000000..849df4c47
--- /dev/null
+++ b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl
@@ -0,0 +1,529 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% js_urls = [ 'js/yui3/yui/yui-min.js',
+ 'extensions/GuidedBugEntry/web/js/products.js',
+ 'extensions/GuidedBugEntry/web/js/guided.js',
+ 'extensions/ProdCompSearch/web/js/prod_comp_search.js',
+ 'js/field.js', 'js/TUI.js', 'js/bug.js' ] %]
+
+[% yui_modules = [ 'history', 'datatable', 'container' ] %]
+[% yui_modules.push('autocomplete') %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Enter A Bug"
+ javascript_urls = js_urls
+ style_urls = [ 'extensions/GuidedBugEntry/web/style/guided.css',
+ 'js/yui/assets/skins/sam/container.css' ]
+ yui = yui_modules
+%]
+
+<iframe id="yui-history-iframe" src="extensions/GuidedBugEntry/web/yui-history-iframe.txt"></iframe>
+<input id="yui-history-field" type="hidden">
+
+<noscript>
+You require JavaScript to use this [% terms.bug %] entry form.<br><br>
+Please use the <a href="enter_bug.cgi?format=__default__">advanced [% terms.bug %] entry form</a>.
+</noscript>
+
+<div id="loading" class="hidden">
+Please wait...
+</div>
+<script type="text/javascript">
+YAHOO.util.Dom.removeClass('loading', 'hidden');
+</script>
+
+<div id="steps">
+[% INCLUDE product_step %]
+[% INCLUDE otherProducts_step %]
+[% INCLUDE dupes_step %]
+[% INCLUDE bugForm_step %]
+</div>
+
+<div id="advanced">
+ <a id="advanced_img" href="enter_bug.cgi?format=__default__"><img
+ src="extensions/GuidedBugEntry/web/images/advanced.png" width="16" height="16" border="0"></a>
+ <a id="advanced_link" href="enter_bug.cgi?format=__default__">Switch to the advanced [% terms.bug %] entry form</a>
+</div>
+
+<script type="text/javascript">
+YAHOO.util.Dom.addClass('loading', 'hidden');
+guided.init();
+guided.detectedPlatform = '[% platform FILTER js %]';
+guided.detectedOpSys = '[% op_sys FILTER js %]';
+guided.currentUser = '[% user.login FILTER js %]';
+guided.openStates = [
+[% FOREACH state = open_states %]
+ '[% state FILTER js%]'
+ [%- "," UNLESS loop.last %]
+[% END %]
+];
+dupes.setLabels(
+ {
+ id: "[% field_descs.bug_id FILTER js %]",
+ summary: "[% field_descs.short_desc FILTER js %]",
+ component: "[% field_descs.component FILTER js %]",
+ status: "[% field_descs.bug_status FILTER js %]",
+ }
+);
+</script>
+<script type="text/javascript" src="page.cgi?id=guided_products.js"></script>
+[% PROCESS global/footer.html.tmpl %]
+
+[%############################################################################%]
+[%# page title #%]
+[%############################################################################%]
+
+[% BLOCK page_title %]
+ <div id="page_title">
+ <h2>Enter A [% terms.Bug %]</h2>
+ <h3>Step [% step_number FILTER html %] of 3</h3>
+ </div>
+[% END %]
+
+[%############################################################################%]
+[%# product step #%]
+[%############################################################################%]
+
+[% BLOCK product_step %]
+<div id="product_step" class="step hidden">
+
+[% INCLUDE page_title
+ step_number = "1"
+%]
+
+[% INCLUDE exits
+ show = "all"
+%]
+
+<table id="products">
+[% INCLUDE 'guided/products.html.tmpl' %]
+[% INCLUDE product_block
+ name="Other Products"
+ icon="other.png"
+ desc="Other Mozilla products which aren't listed here"
+ onclick="guided.setStep('otherProducts')"
+%]
+</table>
+
+<h3>
+ Or search for a Product:
+</h3>
+
+<div id="prod_comp_search_main">
+ [% PROCESS prodcompsearch/form.html.tmpl
+ input_label = "Find product:"
+ format = "guided"
+ script_name = "enter_bug.cgi" %]
+</div>
+
+</div>
+[% END %]
+
+[% BLOCK product_block %]
+ [% IF !caption %]
+ [% caption = name %]
+ [% END %]
+ [% IF !desc %]
+ [% FOREACH c = classifications %]
+ [% FOREACH p = c.products %]
+ [% IF p.name == name %]
+ [% desc = p.description %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+ [% END %]
+ [% END %]
+ <tr>
+ <td class="product_img">
+ <a href="javascript:void(0)"
+ [% IF onclick %]
+ onclick="[% onclick FILTER html %]"
+ [% ELSE %]
+ onclick="product.select('[% name FILTER js %]')"
+ [% END %]
+ ><img src="extensions/GuidedBugEntry/web/images/products/[% icon FILTER uri %]" width="64" height="64"
+ ></a>
+ </td>
+ <td>
+ <h2>
+ <a href="javascript:void(0)"
+ [% IF onclick %]
+ onclick="[% onclick FILTER html %]"
+ [% ELSE %]
+ onclick="product.select('[% name FILTER js %]')"
+ [% END %]
+ >[% caption FILTER html %]</a>
+ </h2>
+ <p>
+ [% desc FILTER html_light %]
+ </p>
+ </td>
+ </tr>
+[% END %]
+
+[%############################################################################%]
+[%# other products step #%]
+[%############################################################################%]
+
+[% BLOCK otherProducts_step %]
+<div id="otherProducts_step" class="step hidden">
+
+[% INCLUDE page_title
+ step_number = "1"
+%]
+
+[% INCLUDE exits
+ show = "all"
+%]
+
+<table id="other_products">
+[% FOREACH c = classifications %]
+ [% IF c.object %]
+ <tr class="classification">
+ <th align="right" valign="top">
+ [% c.object.name FILTER html %]:&nbsp;
+ </th>
+ <td>
+ [% c.object.description FILTER html_light %]
+ </td>
+ </tr>
+ [% END %]
+ [% FOREACH p = c.products %]
+ <tr>
+ <th align="right" valign="top">
+ <a href="javascript:void(0)" onclick="product.select('[% p.name FILTER js %]')">
+ [% p.name FILTER html FILTER no_break %]</a>:&nbsp;
+ </th>
+
+ <td valign="top">[% p.description FILTER html_light %]</td>
+ </tr>
+ [% END %]
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+[% END %]
+</table>
+
+</div>
+[% END %]
+
+[%############################################################################%]
+[%# exits (support/input) #%]
+[%############################################################################%]
+
+[% BLOCK exits %]
+<table class="exits">
+ <tr>
+ <td>
+ <div class="exit_img">
+ <a href="http://www.mozilla.org/support/"
+ ><img src="extensions/GuidedBugEntry/web/images/support.png" width="32" height="32"
+ ></a>
+ </div>
+ </td>
+ <td class="exit_text">
+ <a href="http://www.mozilla.org/support/">I need technical support</a><br>
+ For technical support or help getting your site to work with Mozilla.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="exit_img">
+ <a href="http://input.mozilla.org/feedback/"
+ ><img src="extensions/GuidedBugEntry/web/images/input.png" width="32" height="32"
+ ></a>
+ </div>
+ </td>
+ <td class="exit_text">
+ <a href="http://input.mozilla.org/feedback/#sad">Offer us ideas on how to make Firefox better</a><br>
+ <a href="http://input.mozilla.org/feedback/">Provide feedback about Firefox</a><br>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="exit_img">
+ <img src="extensions/GuidedBugEntry/web/images/webbug.png" width="32" height="32">
+ </div>
+ </td>
+ <td class="exit_text_last">
+ <a href="enter_bug.cgi?format=guided&amp;product=Core">Report an issue with Firefox on a site that I've developed</a><br>
+ <a href="http://input.mozilla.org/feedback/#sad">Report an issue with a web site that I use</a><br>
+ </td>
+ </tr>
+</table>
+
+<h3>
+ None of the above; my [% terms.bug %] is in:
+</h3>
+[% END %]
+
+[% BLOCK exit_block %]
+ <tr>
+ <td>
+ <div class="exit_img">
+ <a href="[% href FILTER none %]"
+ ><img src="extensions/GuidedBugEntry/web/images/[% icon FILTER uri %]" width="32" height="32"
+ ></a>
+ </div>
+ </td>
+ <td width="100%">
+ <h2>
+ <a href="[% href FILTER none %]">[% name FILTER html %]</a>
+ </h2>
+ [% desc FILTER html %]
+ </td>
+ </tr>
+[% END %]
+
+[%############################################################################%]
+[%# duplicates step #%]
+[%############################################################################%]
+
+[% BLOCK dupes_step %]
+<div id="dupes_step" class="step hidden">
+
+[% INCLUDE page_title
+ step_number = "2"
+%]
+
+<p>
+Product: <b><span id="dupes_product_name">?</span></b>:
+(<a href="javascript:void(0)" onclick="guided.setStep('product')">Change</a>)
+</p>
+
+<table border="0" cellpadding="5" cellspacing="0" id="product_support" class="hidden">
+<tr>
+<td>
+ <img src="extensions/GuidedBugEntry/web/images/message.png" width="24" height="24">
+</td>
+<td id="product_support_message">&nbsp;</td>
+</table>
+
+<div id="dupe_form">
+ <p>
+ Please summarise your issue or request in one sentence:
+ </p>
+ <input id="dupes_summary" value="Short summary of issue" spellcheck="true" placeholder="Short summary of issue">
+ <button id="dupes_search">Find similar issues</button>
+ <button id="dupes_continue_button_top" onclick="guided.setStep('bugForm')">My issue is not listed</button>
+</div>
+
+<div id="dupes_list"></div>
+<div id="dupes_continue">
+<button id="dupes_continue_button_bottom" onclick="guided.setStep('bugForm')">My issue is not listed</button>
+</div>
+
+</div>
+[% END %]
+
+[%############################################################################%]
+[%# bug form step #%]
+[%############################################################################%]
+
+[% BLOCK bugForm_step %]
+<div id="bugForm_step" class="step hidden">
+
+[% INCLUDE page_title
+ step_number = "3"
+%]
+
+<form method="post" action="post_bug.cgi" enctype="multipart/form-data" onsubmit="return bugForm.validate()">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+<input type="hidden" name="product" id="product" value="">
+<input type="hidden" name="component" id="component" value="">
+<input type="hidden" name="bug_severity" value="normal">
+<input type="hidden" name="rep_platform" id="rep_platform" value="All">
+<input type="hidden" name="priority" value="--">
+<input type="hidden" name="op_sys" id="op_sys" value="All">
+<input type="hidden" name="version" id="version" value="">
+<input type="hidden" name="comment" id="comment" value="">
+<input type="hidden" name="format" value="guided">
+<input type="hidden" name="user_agent" id="user_agent" value="">
+<input type="hidden" name="build_id" id="build_id" value="">
+
+<ul>
+<li>Please fill out this form clearly, precisely and in as much detail as you can manage.</li>
+<li>Please report only a single problem at a time.</li>
+<li><a href="https://developer.mozilla.org/en/Bug_writing_guidelines" target="_blank">These guidelines</a>
+explain how to write effective [% terms.bug %] reports.</li>
+</ul>
+
+<table id="bugForm" cellspacing="0">
+
+<tr class="odd">
+ <td class="label">Summary:</td>
+ <td width="100%" colspan="2">
+ <input name="short_desc" id="short_desc" class="textInput" spellcheck="true">
+ </td>
+ <td valign="top">
+ [% PROCESS help id="summary_help" %]
+ <div id="summary_help" class="hidden help">
+ A sentence which summarises the problem. Please be descriptive and use lots of keywords.<br>
+ <br>
+ <span class="help-bad">Bad example</span>: mail crashed<br>
+ <span class="help-good">Good example</span>: crash if I close the mail window while checking for new POP mail
+ </div>
+ </td>
+</tr>
+
+<tr class="even">
+ <td class="label">Product:</td>
+ <td id="productTD">
+ <span id="product_label"></span>
+ (<a href="javascript:void(0)" onclick="guided.setStep('product')">Change</a>)
+ </td>
+ <td id="versionTD" class="hidden">
+ <span class="label">Version:
+ <select id="version_select" onchange="bugForm.onVersionChange(this.value)">
+ </select>
+ </td>
+ <td valign="top">
+ [% PROCESS help id="product_help" %]
+ <div id="product_help" class="hidden help">
+ The Product and Version you are reporting the issue with.
+ </div>
+</tr>
+
+<tr class="odd" id="componentTR">
+ <td valign="top">
+ <div class="label">
+ Component:
+ </div>
+ (<a id="list_comp" href="describecomponents.cgi" target="_blank"
+ title="Show a list of all components and descriptions (in a new window)."
+ >List</a>)
+ </td>
+ <td valign="top" colspan="2">
+ <select id="component_select" onchange="bugForm.onComponentChange(this.value)" class="mandatory">
+ </select>
+ <div id="component_description"></div>
+ </td>
+ <td valign="top">
+ [% PROCESS help id="component_help" %]
+ <div id="component_help" class="hidden help">
+ The area where the problem occurs.<br>
+ <br>
+ If you are unsure which component to use, select a 'General' component.
+ </div>
+</tr>
+
+<tr class="even">
+ <td class="label" colspan="3">What did you do?</td>
+ <td valign="top">
+ [% PROCESS help id="steps_help" %]
+ <div id="steps_help" class="hidden help">
+ Please be as specific as possible about what what you did
+ to cause the problem. Providing step-by-step instructions
+ would be ideal.<br>
+ <br>
+ Include any relevant URLs and special setup steps.<br>
+ <br>
+ <span class="help-bad">Bad example</span>: Mozilla crashed. You suck!<br>
+ <span class="help-good">Good example</span>: After a crash which happened
+ when I was sorting in the Bookmark Manager, all of my top-level bookmark
+ folders beginning with the letters Q to Z are no longer present.
+ </div>
+ </td>
+</tr>
+<tr class="even">
+ <td colspan="3"><textarea id="bug_steps" name="bug_steps" rows="5"></textarea></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr class="odd">
+ <td class="label" colspan="3">What happened?</td>
+ <td valign="top">
+ [% PROCESS help id="actual_help" %]
+ <div id="actual_help" class="hidden help">
+ What happened after you performed the steps above?
+ </div>
+</tr>
+<tr class="odd">
+ <td colspan="3"><textarea id="actual" name="actual" rows="5"></textarea></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr class="even">
+ <td class="label" colspan="3">What should have happened?</td>
+ <td valign="top">
+ [% PROCESS help id="expected_help" %]
+ <div id="expected_help" class="hidden help">
+ What should the software have done instead?
+ </div>
+</tr>
+<tr class="even">
+ <td colspan="3"><textarea id="expected" name="expected" rows="5"></textarea></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr class="odd">
+ <td class="label">Attach a file:</td>
+ <td colspan="2">
+ <input type="file" name="data" id="data" size="50" onchange="bugForm.onFileChange()">
+ <input type="hidden" name="contenttypemethod" value="autodetect">
+ <button id="reset_data" onclick="return bugForm.onFileClear()" disabled>Clear</button>
+ </td>
+ <td valign="top">
+ [% PROCESS help id="file_help" %]
+ <div id="file_help" class="hidden help">
+ If a file helps explain the issue better, such as a screenshot, please
+ attach one here.
+ </div>
+ </td>
+</tr>
+<tr class="odd">
+ <td class="label">File Description:</td>
+ <td colspan="2"><input type="text" name="description" id="data_description" class="textInput" disabled></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr class="even">
+ <td class="label">Security:</td>
+ <td colspan="2">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <input type="checkbox" name="groups" value="core-security" id="groups">
+ </td>
+ <td>
+ <label for="groups">Many users could be harmed by this security problem:
+ it should be kept hidden from the public until it is resolved.</label>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr class="odd">
+ <td>&nbsp;</td>
+ <td colspan="2" id="submitTD">
+ <input type="submit" id="submit" value="Submit [% terms.Bug %]">
+ </td>
+ <td>&nbsp;</td>
+</tr>
+
+</table>
+
+</form>
+
+</div>
+[% END %]
+
+[%############################################################################%]
+[%# help block #%]
+[%############################################################################%]
+
+[% BLOCK help %]
+<img src="extensions/GuidedBugEntry/web/images/help.png" width="16" height="16" class="help_image"
+ helpid="[% id FILTER html %]" onMouseOver="bugForm.showHelp(this)" onMouseOut="bugForm.hideHelp(this)"
+ >
+[% END %]
diff --git a/extensions/GuidedBugEntry/template/en/default/guided/products.html.tmpl b/extensions/GuidedBugEntry/template/en/default/guided/products.html.tmpl
new file mode 100644
index 000000000..f775f837c
--- /dev/null
+++ b/extensions/GuidedBugEntry/template/en/default/guided/products.html.tmpl
@@ -0,0 +1,51 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% INCLUDE product_block
+ name="Firefox"
+ icon="firefox.png"
+%]
+[% INCLUDE product_block
+ name="Boot2Gecko"
+ icon="firefox.png"
+ caption="Firefox OS"
+%]
+[% INCLUDE product_block
+ name="Firefox for Android"
+ icon="firefox.png"
+%]
+[% INCLUDE product_block
+ name="Firefox for Metro"
+ icon="firefox.png"
+%]
+[% INCLUDE product_block
+ name="Marketplace"
+ icon="marketplace.png"
+%]
+[% INCLUDE product_block
+ name="Thunderbird"
+ icon="thunderbird.png"
+%]
+[% INCLUDE product_block
+ name="SeaMonkey"
+ icon="seamonkey.png"
+%]
+[% INCLUDE product_block
+ name="Core"
+ icon="core.png"
+%]
+[% INCLUDE product_block
+ name="Mozilla Localizations"
+ icon="dino.png"
+ caption="Localizations"
+%]
+[% INCLUDE product_block
+ name="Mozilla Services"
+ icon="dino.png"
+ caption="Services"
+%]
diff --git a/extensions/GuidedBugEntry/template/en/default/pages/guided_products.js.tmpl b/extensions/GuidedBugEntry/template/en/default/pages/guided_products.js.tmpl
new file mode 100644
index 000000000..268fe06f8
--- /dev/null
+++ b/extensions/GuidedBugEntry/template/en/default/pages/guided_products.js.tmpl
@@ -0,0 +1,26 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%# this file allows us to pull in data defined in the BMO ext %]
+
+[% IF formats %]
+ [% FOREACH product = formats %]
+ if (!products['[% product.key FILTER js %]']) [% ~%]
+ products['[% product.key FILTER js %]'] = {};
+ products['[% product.key FILTER js %]'].format = '[% product.value FILTER js %]';
+ [% END %]
+[% END %]
+
+[% IF products %]
+ [% FOREACH product = products %]
+ if (!products['[% product.key FILTER js %]']) [% ~%]
+ products['[% product.key FILTER js %]'] = {};
+ products['[% product.key FILTER js %]'].secgroup = '[% product.value FILTER js %]';
+ [% END %]
+[% END %]
+
diff --git a/extensions/GuidedBugEntry/web/images/advanced.png b/extensions/GuidedBugEntry/web/images/advanced.png
new file mode 100644
index 000000000..71a3fcb78
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/advanced.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/help.png b/extensions/GuidedBugEntry/web/images/help.png
new file mode 100644
index 000000000..5c870176d
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/help.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/input.png b/extensions/GuidedBugEntry/web/images/input.png
new file mode 100644
index 000000000..34c10e989
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/input.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/message.png b/extensions/GuidedBugEntry/web/images/message.png
new file mode 100644
index 000000000..55b6add19
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/message.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/camino.png b/extensions/GuidedBugEntry/web/images/products/camino.png
new file mode 100644
index 000000000..c833b4d04
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/camino.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/core.png b/extensions/GuidedBugEntry/web/images/products/core.png
new file mode 100644
index 000000000..b9c5053f6
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/core.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/dino.png b/extensions/GuidedBugEntry/web/images/products/dino.png
new file mode 100644
index 000000000..9e0470a07
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/dino.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/fennec.png b/extensions/GuidedBugEntry/web/images/products/fennec.png
new file mode 100644
index 000000000..ebad7e358
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/fennec.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/firefox.png b/extensions/GuidedBugEntry/web/images/products/firefox.png
new file mode 100644
index 000000000..582a6952a
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/firefox.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/labs.png b/extensions/GuidedBugEntry/web/images/products/labs.png
new file mode 100644
index 000000000..346e0ef06
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/labs.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/marketplace.png b/extensions/GuidedBugEntry/web/images/products/marketplace.png
new file mode 100644
index 000000000..62025a2a8
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/marketplace.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/mozilla.png b/extensions/GuidedBugEntry/web/images/products/mozilla.png
new file mode 100644
index 000000000..e506328bc
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/mozilla.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/other.png b/extensions/GuidedBugEntry/web/images/products/other.png
new file mode 100644
index 000000000..e436c22ae
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/other.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/seamonkey.png b/extensions/GuidedBugEntry/web/images/products/seamonkey.png
new file mode 100644
index 000000000..fcb261ae1
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/seamonkey.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/sunbird.png b/extensions/GuidedBugEntry/web/images/products/sunbird.png
new file mode 100644
index 000000000..6b15c257d
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/sunbird.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/products/thunderbird.png b/extensions/GuidedBugEntry/web/images/products/thunderbird.png
new file mode 100644
index 000000000..f3523183a
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/products/thunderbird.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/sumo.png b/extensions/GuidedBugEntry/web/images/sumo.png
new file mode 100644
index 000000000..d5773647c
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/sumo.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/support.png b/extensions/GuidedBugEntry/web/images/support.png
new file mode 100644
index 000000000..2320ea74a
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/support.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/throbber.gif b/extensions/GuidedBugEntry/web/images/throbber.gif
new file mode 100644
index 000000000..bc4fa6561
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/throbber.gif
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/warning.png b/extensions/GuidedBugEntry/web/images/warning.png
new file mode 100644
index 000000000..86bed170d
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/warning.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/images/webbug.png b/extensions/GuidedBugEntry/web/images/webbug.png
new file mode 100644
index 000000000..949cfbc59
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/images/webbug.png
Binary files differ
diff --git a/extensions/GuidedBugEntry/web/js/guided.js b/extensions/GuidedBugEntry/web/js/guided.js
new file mode 100644
index 000000000..98d637d60
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/js/guided.js
@@ -0,0 +1,924 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+// global
+
+var Dom = YAHOO.util.Dom;
+var Event = YAHOO.util.Event;
+var History = YAHOO.util.History;
+
+var guided = {
+ _currentStep: '',
+ detectedPlatform: '',
+ detectedOpSys: '',
+ currentUser: '',
+ openStates: [],
+ updateStep: true,
+
+ setStep: function(newStep, noSetHistory) {
+ // initialise new step
+ this.updateStep = true;
+ switch(newStep) {
+ case 'product':
+ product.onShow();
+ break;
+ case 'otherProducts':
+ otherProducts.onShow();
+ break;
+ case 'dupes':
+ dupes.onShow();
+ break;
+ case 'bugForm':
+ bugForm.onShow();
+ break;
+ default:
+ guided.setStep('product');
+ return;
+ }
+
+ if (!this.updateStep)
+ return;
+
+ // change visibility of _step div
+ if (this._currentStep)
+ Dom.addClass(this._currentStep + '_step', 'hidden');
+ this._currentStep = newStep;
+ Dom.removeClass(this._currentStep + '_step', 'hidden');
+
+ // scroll to top of page to mimic real navigation
+ scroll(0,0);
+
+ // update history
+ if (History && !noSetHistory) {
+ History.navigate('h', newStep + '|' + product.getName() +
+ (product.getPreselectedComponent() ? '|' + product.getPreselectedComponent() : '')
+ );
+ }
+ },
+
+ init: function() {
+ // init history manager
+ try {
+ History.register('h', History.getBookmarkedState('h') || 'product',
+ this._onStateChange);
+ History.initialize("yui-history-field", "yui-history-iframe");
+ History.onReady(function () {
+ guided._onStateChange(History.getCurrentState('h'), true);
+ });
+ } catch(err) {
+ History = false;
+ }
+
+ // init steps
+ product.onInit();
+ dupes.onInit();
+ bugForm.onInit();
+ },
+
+ _onStateChange: function(state, noSetHistory) {
+ state = state.split('|');
+ product.setName(state[1] || '');
+ product.setPreselectedComponent(state[2] || '');
+ guided.setStep(state[0], noSetHistory);
+ },
+
+ setAdvancedLink: function() {
+ href = 'enter_bug.cgi?format=__default__' +
+ '&product=' + encodeURIComponent(product.getName()) +
+ '&short_desc=' + encodeURIComponent(dupes.getSummary());
+ Dom.get('advanced_img').href = href;
+ Dom.get('advanced_link').href = href;
+ }
+};
+
+// product step
+
+var product = {
+ details: false,
+ _counter: 0,
+ _loaded: '',
+ _preselectedComponent: '',
+
+ onInit: function() { },
+
+ onShow: function() {
+ Dom.removeClass('advanced', 'hidden');
+ },
+
+ select: function(productName) {
+ // called when a product is selected
+ this.setName(productName);
+ dupes.reset();
+ guided.setStep('dupes');
+ },
+
+ getName: function() {
+ return Dom.get('product').value;
+ },
+
+ getPreselectedComponent: function() {
+ return this._preselectedComponent;
+ },
+
+ setPreselectedComponent: function(value) {
+ this._preselectedComponent = value;
+ },
+
+ _getNameAndRelated: function() {
+ var result = [];
+
+ var name = this.getName();
+ result.push(name);
+
+ if (products[name] && products[name].related) {
+ for (var i = 0, n = products[name].related.length; i < n; i++) {
+ result.push(products[name].related[i]);
+ }
+ }
+
+ return result;
+ },
+
+ setName: function(productName) {
+ if (productName == this.getName() && this.details)
+ return;
+
+ // display the product name
+ Dom.get('product').value = productName;
+ Dom.get('product_label').innerHTML = YAHOO.lang.escapeHTML(productName);
+ Dom.get('dupes_product_name').innerHTML = YAHOO.lang.escapeHTML(productName);
+ Dom.get('list_comp').href = 'describecomponents.cgi?product=' + encodeURIComponent(productName);
+ guided.setAdvancedLink();
+
+ if (productName == '') {
+ Dom.addClass("product_support", "hidden");
+ return;
+ }
+
+ // use the correct security group
+ if (products[productName] && products[productName].secgroup) {
+ Dom.get('groups').value = products[productName].secgroup;
+ } else {
+ Dom.get('groups').value = products['_default'].secgroup;
+ }
+
+ // use the correct platform & op_sys
+ if (products[productName] && products[productName].detectPlatform) {
+ Dom.get('rep_platform').value = guided.detectedPlatform;
+ Dom.get('op_sys').value = guided.detectedOpSys;
+ } else {
+ Dom.get('rep_platform').value = 'All';
+ Dom.get('op_sys').value = 'All';
+ }
+
+ // show support message
+ if (products[productName] && products[productName].support) {
+ Dom.get("product_support_message").innerHTML = products[productName].support;
+ Dom.removeClass("product_support", "hidden");
+ } else {
+ Dom.addClass("product_support", "hidden");
+ }
+
+ // show/hide component selection row
+ if (products[productName] && products[productName].noComponentSelection) {
+ if (!Dom.hasClass('componentTR', 'hidden')) {
+ Dom.addClass('componentTR', 'hidden');
+ bugForm.toggleOddEven();
+ }
+ } else {
+ if (Dom.hasClass('componentTR', 'hidden')) {
+ Dom.removeClass('componentTR', 'hidden');
+ bugForm.toggleOddEven();
+ }
+ }
+
+ if (this._loaded == productName)
+ return;
+
+ // grab the product information
+ this.details = false;
+ this._loaded = productName;
+ YAHOO.util.Connect.setDefaultPostHeader('application/json; charset=UTF-8');
+ YAHOO.util.Connect.asyncRequest(
+ 'POST',
+ 'jsonrpc.cgi',
+ {
+ success: function(res) {
+ try {
+ data = YAHOO.lang.JSON.parse(res.responseText);
+ if (data.error)
+ throw(data.error.message);
+ product.details = data.result.products[0];
+ bugForm.onProductUpdated();
+ } catch (err) {
+ product.details = false;
+ bugForm.onProductUpdated();
+ if (err) {
+ alert('Failed to retreive components for product "' +
+ productName + '":' + "\n\n" + err);
+ if (console)
+ console.error(err);
+ }
+ }
+ },
+ failure: function(res) {
+ this._loaded = '';
+ product.details = false;
+ bugForm.onProductUpdated();
+ if (res.responseText) {
+ alert('Failed to retreive components for product "' +
+ productName + '":' + "\n\n" + res.responseText);
+ if (console)
+ console.error(res);
+ }
+ }
+ },
+ YAHOO.lang.JSON.stringify({
+ version: "1.1",
+ method: "Product.get",
+ id: ++this._counter,
+ params: {
+ names: [productName],
+ exclude_fields: ['internals', 'milestones']
+ }
+ }
+ )
+ );
+ }
+};
+
+// other products step
+
+var otherProducts = {
+ onInit: function() { },
+
+ onShow: function() {
+ Dom.removeClass('advanced', 'hidden');
+ }
+};
+
+// duplicates step
+
+var dupes = {
+ _counter: 0,
+ _dataTable: null,
+ _dataTableColumns: null,
+ _elSummary: null,
+ _elSearch: null,
+ _elList: null,
+ _currentSearchQuery: '',
+
+ onInit: function() {
+ this._elSummary = Dom.get('dupes_summary');
+ this._elSearch = Dom.get('dupes_search');
+ this._elList = Dom.get('dupes_list');
+
+ Event.onBlur(this._elSummary, this._onSummaryBlur);
+ Event.addListener(this._elSummary, 'input', this._onSummaryBlur);
+ Event.addListener(this._elSummary, 'keydown', this._onSummaryKeyDown);
+ Event.addListener(this._elSummary, 'keyup', this._onSummaryKeyUp);
+ Event.addListener(this._elSearch, 'click', this._doSearch);
+ },
+
+ setLabels: function(labels) {
+ this._dataTableColumns = [
+ { key: "id", label: labels.id, formatter: this._formatId },
+ { key: "summary", label: labels.summary, formatter: "text" },
+ { key: "component", label: labels.component, formatter: "text" },
+ { key: "status", label: labels.status, formatter: this._formatStatus },
+ { key: "update_token", label: '', formatter: this._formatCc }
+ ];
+ },
+
+ _initDataTable: function() {
+ var dataSource = new YAHOO.util.XHRDataSource("jsonrpc.cgi");
+ dataSource.connTimeout = 15000;
+ dataSource.connMethodPost = true;
+ dataSource.connXhrMode = "cancelStaleRequests";
+ dataSource.maxCacheEntries = 3;
+ dataSource.responseSchema = {
+ resultsList : "result.bugs",
+ metaFields : { error: "error", jsonRpcId: "id" }
+ };
+ // DataSource can't understand a JSON-RPC error response, so
+ // we have to modify the result data if we get one.
+ dataSource.doBeforeParseData =
+ function(oRequest, oFullResponse, oCallback) {
+ if (oFullResponse.error) {
+ oFullResponse.result = {};
+ oFullResponse.result.bugs = [];
+ if (console)
+ console.error("JSON-RPC error:", oFullResponse.error);
+ }
+ return oFullResponse;
+ };
+ dataSource.subscribe('dataErrorEvent',
+ function() {
+ dupes._currentSearchQuery = '';
+ }
+ );
+
+ this._dataTable = new YAHOO.widget.DataTable(
+ 'dupes_list',
+ this._dataTableColumns,
+ dataSource,
+ {
+ initialLoad: false,
+ MSG_EMPTY: 'No similar issues found.',
+ MSG_ERROR: 'An error occurred while searching for similar issues,' +
+ ' please try again.'
+ }
+ );
+ },
+
+ _formatId: function(el, oRecord, oColumn, oData) {
+ el.innerHTML = '<a href="show_bug.cgi?id=' + oData +
+ '" target="_blank">' + oData + '</a>';
+ },
+
+ _formatStatus: function(el, oRecord, oColumn, oData) {
+ var resolution = oRecord.getData('resolution');
+ var bug_status = display_value('bug_status', oData);
+ if (resolution) {
+ el.innerHTML = bug_status + ' ' +
+ display_value('resolution', resolution);
+ } else {
+ el.innerHTML = bug_status;
+ }
+ },
+
+ _formatCc: function(el, oRecord, oColumn, oData) {
+ var cc = oRecord.getData('cc');
+ var isCCed = false;
+ for (var i = 0, n = cc.length; i < n; i++) {
+ if (cc[i] == guided.currentUser) {
+ isCCed = true;
+ break;
+ }
+ }
+ dupes._buildCcHTML(el, oRecord.getData('id'), oRecord.getData('status'),
+ isCCed);
+ },
+
+ _buildCcHTML: function(el, id, bugStatus, isCCed) {
+ while (el.childNodes.length > 0)
+ el.removeChild(el.firstChild);
+
+ var isOpen = false;
+ for (var i = 0, n = guided.openStates.length; i < n; i++) {
+ if (guided.openStates[i] == bugStatus) {
+ isOpen = true;
+ break;
+ }
+ }
+
+ if (!isOpen && !isCCed) {
+ // you can't cc yourself to a closed bug here
+ return;
+ }
+
+ var button = document.createElement('button');
+ button.setAttribute('type', 'button');
+ if (isCCed) {
+ button.innerHTML = 'Stop&nbsp;following';
+ button.onclick = function() {
+ dupes.updateFollowing(el, id, bugStatus, button, false); return false;
+ };
+ } else {
+ button.innerHTML = 'Follow&nbsp;bug';
+ button.onclick = function() {
+ dupes.updateFollowing(el, id, bugStatus, button, true); return false;
+ };
+ }
+ el.appendChild(button);
+ },
+
+ updateFollowing: function(el, bugID, bugStatus, button, follow) {
+ button.disabled = true;
+ button.innerHTML = 'Updating...';
+
+ var ccObject;
+ if (follow) {
+ ccObject = { add: [ guided.currentUser ] };
+ } else {
+ ccObject = { remove: [ guided.currentUser ] };
+ }
+
+ YAHOO.util.Connect.setDefaultPostHeader('application/json; charset=UTF-8');
+ YAHOO.util.Connect.asyncRequest(
+ 'POST',
+ 'jsonrpc.cgi',
+ {
+ success: function(res) {
+ data = YAHOO.lang.JSON.parse(res.responseText);
+ if (data.error)
+ throw(data.error.message);
+ dupes._buildCcHTML(el, bugID, bugStatus, follow);
+ },
+ failure: function(res) {
+ dupes._buildCcHTML(el, bugID, bugStatus, !follow);
+ if (res.responseText)
+ alert("Update failed:\n\n" + res.responseText);
+ }
+ },
+ YAHOO.lang.JSON.stringify({
+ version: "1.1",
+ method: "Bug.update",
+ id: ++this._counter,
+ params: {
+ ids: [ bugID ],
+ cc : ccObject
+ }
+ })
+ );
+ },
+
+ reset: function() {
+ this._elSummary.value = '';
+ Dom.addClass(this._elList, 'hidden');
+ Dom.addClass('dupes_continue', 'hidden');
+ this._elList.innerHTML = '';
+ this._showProductSupport();
+ this._currentSearchQuery = '';
+ },
+
+ _showProductSupport: function() {
+ var elSupport = Dom.get('product_support_' +
+ product.getName().replace(' ', '_').toLowerCase());
+ var supportElements = Dom.getElementsByClassName('product_support');
+ for (var i = 0, n = supportElements.length; i < n; i++) {
+ if (supportElements[i] == elSupport) {
+ Dom.removeClass(elSupport, 'hidden');
+ } else {
+ Dom.addClass(supportElements[i], 'hidden');
+ }
+ }
+ },
+
+ onShow: function() {
+ this._showProductSupport();
+ this._onSummaryBlur();
+
+ // hide the advanced form and top continue button entry until
+ // a search has happened
+ Dom.addClass('advanced', 'hidden');
+ Dom.addClass('dupes_continue_button_top', 'hidden');
+
+ if (!this._elSearch.disabled && this.getSummary().length >= 4) {
+ // do an immediate search after a page refresh if there's a query
+ this._doSearch();
+
+ } else {
+ // prepare for a search
+ this.reset();
+ }
+ },
+
+ _onSummaryBlur: function() {
+ dupes._elSearch.disabled = dupes._elSummary.value == '';
+ guided.setAdvancedLink();
+ },
+
+ _onSummaryKeyDown: function(e) {
+ // map <enter> to doSearch()
+ if (e && (e.keyCode == 13)) {
+ dupes._doSearch();
+ Event.stopPropagation(e);
+ }
+ },
+
+ _onSummaryKeyUp: function(e) {
+ // disable search button until there's a query
+ dupes._elSearch.disabled = YAHOO.lang.trim(dupes._elSummary.value) == '';
+ },
+
+ _doSearch: function() {
+ if (dupes.getSummary().length < 4) {
+ alert('The summary must be at least 4 characters long.');
+ return;
+ }
+ dupes._elSummary.blur();
+
+ // don't query if we already have the results (or they are pending)
+ if (dupes._currentSearchQuery == dupes.getSummary())
+ return;
+ dupes._currentSearchQuery = dupes.getSummary();
+
+ // initialise the datatable as late as possible
+ dupes._initDataTable();
+
+ try {
+ // run the search
+ Dom.removeClass(dupes._elList, 'hidden');
+
+ dupes._dataTable.showTableMessage(
+ 'Searching for similar issues...&nbsp;&nbsp;&nbsp;' +
+ '<img src="extensions/GuidedBugEntry/web/images/throbber.gif"' +
+ ' width="16" height="11">',
+ YAHOO.widget.DataTable.CLASS_LOADING
+ );
+ var json_object = {
+ version: "1.1",
+ method: "Bug.possible_duplicates",
+ id: ++dupes._counter,
+ params: {
+ product: product._getNameAndRelated(),
+ summary: dupes.getSummary(),
+ limit: 12,
+ include_fields: [ "id", "summary", "status", "resolution",
+ "update_token", "cc", "component" ]
+ }
+ };
+
+ dupes._dataTable.getDataSource().sendRequest(
+ YAHOO.lang.JSON.stringify(json_object),
+ {
+ success: dupes._onDupeResults,
+ failure: dupes._onDupeResults,
+ scope: dupes._dataTable,
+ argument: dupes._dataTable.getState()
+ }
+ );
+
+ Dom.get('dupes_continue_button_top').disabled = true;
+ Dom.get('dupes_continue_button_bottom').disabled = true;
+ Dom.removeClass('dupes_continue', 'hidden');
+ } catch(err) {
+ if (console)
+ console.error(err.message);
+ }
+ },
+
+ _onDupeResults: function(sRequest, oResponse, oPayload) {
+ Dom.removeClass('advanced', 'hidden');
+ Dom.removeClass('dupes_continue_button_top', 'hidden');
+ Dom.get('dupes_continue_button_top').disabled = false;
+ Dom.get('dupes_continue_button_bottom').disabled = false;
+ dupes._dataTable.onDataReturnInitializeTable(sRequest, oResponse,
+ oPayload);
+ },
+
+ getSummary: function() {
+ var summary = YAHOO.lang.trim(this._elSummary.value);
+ // work around chrome bug
+ if (summary == dupes._elSummary.getAttribute('placeholder')) {
+ return '';
+ } else {
+ return summary;
+ }
+ }
+};
+
+// bug form step
+
+var bugForm = {
+ _visibleHelpPanel: null,
+ _mandatoryFields: [],
+
+ onInit: function() {
+ Dom.get('user_agent').value = navigator.userAgent;
+ if (navigator.buildID && navigator.buildID != navigator.userAgent) {
+ Dom.get('build_id').value = navigator.buildID;
+ }
+ Event.addListener(Dom.get('short_desc'), 'blur', function() {
+ Dom.get('dupes_summary').value = Dom.get('short_desc').value;
+ guided.setAdvancedLink();
+ });
+ },
+
+ onShow: function() {
+ // check for a forced format
+ var productName = product.getName();
+ if (products[productName] && products[productName].format) {
+ Dom.addClass('advanced', 'hidden');
+ document.location.href = 'enter_bug.cgi?format=' + encodeURIComponent(products[productName].format) +
+ '&product=' + encodeURIComponent(productName) +
+ '&short_desc=' + encodeURIComponent(dupes.getSummary());
+ guided.updateStep = false;
+ return;
+ }
+ Dom.removeClass('advanced', 'hidden');
+ // default the summary to the dupes query
+ Dom.get('short_desc').value = dupes.getSummary();
+ this.resetSubmitButton();
+ if (Dom.get('component_select').length == 0)
+ this.onProductUpdated();
+ this.onFileChange();
+ for (var i = 0, n = this._mandatoryFields.length; i < n; i++) {
+ Dom.removeClass(this._mandatoryFields[i], 'missing');
+ }
+ },
+
+ resetSubmitButton: function() {
+ Dom.get('submit').disabled = false;
+ Dom.get('submit').value = 'Submit Bug';
+ },
+
+ onProductUpdated: function() {
+ var productName = product.getName();
+
+ // init
+ var elComponents = Dom.get('component_select');
+ Dom.addClass('component_description', 'hidden');
+ elComponents.options.length = 0;
+
+ var elVersions = Dom.get('version_select');
+ elVersions.length = 0;
+
+ // product not loaded yet, bail out
+ if (!product.details) {
+ Dom.addClass('versionTH', 'hidden');
+ Dom.addClass('versionTD', 'hidden');
+ Dom.get('productTD').colSpan = 2;
+ Dom.get('submit').disabled = true;
+ return;
+ }
+ Dom.get('submit').disabled = false;
+
+ // filter components
+ if (products[productName] && products[productName].componentFilter) {
+ product.details.components = products[productName].componentFilter(product.details.components);
+ }
+
+ // build components
+
+ var elComponent = Dom.get('component');
+ if (products[productName] && products[productName].noComponentSelection) {
+
+ elComponent.value = products[productName].defaultComponent;
+ bugForm._mandatoryFields = [ 'short_desc', 'version_select' ];
+
+ } else {
+
+ bugForm._mandatoryFields = [ 'short_desc', 'component_select', 'version_select' ];
+
+ // check for the default component
+ var defaultRegex;
+ if (product.getPreselectedComponent()) {
+ defaultRegex = new RegExp('^' + quoteMeta(product.getPreselectedComponent()) + '$', 'i')
+ } else if(products[productName] && products[productName].defaultComponent) {
+ defaultRegex = new RegExp('^' + quoteMeta(products[productName].defaultComponent) + '$', 'i')
+ } else {
+ defaultRegex = new RegExp('General', 'i');
+ }
+
+ var preselectedComponent = false;
+ for (var i = 0, n = product.details.components.length; i < n; i++) {
+ var component = product.details.components[i];
+ if (component.is_active == '1') {
+ if (defaultRegex.test(component.name)) {
+ preselectedComponent = component.name;
+ break;
+ }
+ }
+ }
+
+ // if there isn't a default component, default to blank
+ if (!preselectedComponent) {
+ elComponents.options[elComponents.options.length] = new Option('', '');
+ }
+
+ // build component select
+ for (var i = 0, n = product.details.components.length; i < n; i++) {
+ var component = product.details.components[i];
+ if (component.is_active == '1') {
+ elComponents.options[elComponents.options.length] =
+ new Option(component.name, component.name);
+ }
+ }
+
+ var validComponent = false;
+ for (var i = 0, n = elComponents.options.length; i < n && !validComponent; i++) {
+ if (elComponents.options[i].value == elComponent.value)
+ validComponent = true;
+ }
+ if (!validComponent)
+ elComponent.value = '';
+ if (elComponent.value == '' && preselectedComponent)
+ elComponent.value = preselectedComponent;
+ if (elComponent.value != '') {
+ elComponents.value = elComponent.value;
+ this.onComponentChange(elComponent.value);
+ }
+
+ }
+
+ // build versions
+ var defaultVersion = '';
+ var currentVersion = Dom.get('version').value;
+ for (var i = 0, n = product.details.versions.length; i < n; i++) {
+ var version = product.details.versions[i];
+ if (version.is_active == '1') {
+ elVersions.options[elVersions.options.length] =
+ new Option(version.name, version.name);
+ if (currentVersion == version.name)
+ defaultVersion = version.name;
+ }
+ }
+
+ if (!defaultVersion) {
+ // try to detect version on a per-product basis
+ if (products[productName] && products[productName].version) {
+ var detectedVersion = products[productName].version();
+ var options = elVersions.options;
+ for (var i = 0, n = options.length; i < n; i++) {
+ if (options[i].value == detectedVersion) {
+ defaultVersion = detectedVersion;
+ break;
+ }
+ }
+ }
+ }
+ if (!defaultVersion) {
+ // load last selected version
+ defaultVersion = YAHOO.util.Cookie.get('VERSION-' + productName);
+ }
+
+ if (elVersions.length > 1) {
+ // more than one version, show select
+ Dom.get('productTD').colSpan = 1;
+ Dom.removeClass('versionTH', 'hidden');
+ Dom.removeClass('versionTD', 'hidden');
+
+ } else {
+ // if there's only one version, we don't need to ask the user
+ Dom.addClass('versionTH', 'hidden');
+ Dom.addClass('versionTD', 'hidden');
+ Dom.get('productTD').colSpan = 2;
+ defaultVersion = elVersions.options[0].value;
+ }
+
+ if (defaultVersion) {
+ elVersions.value = defaultVersion;
+
+ } else {
+ // no default version, select an empty value to force a decision
+ var opt = new Option('', '');
+ try {
+ // standards
+ elVersions.add(opt, elVersions.options[0]);
+ } catch(ex) {
+ // ie only
+ elVersions.add(opt, 0);
+ }
+ elVersions.value = '';
+ }
+ bugForm.onVersionChange(elVersions.value);
+ },
+
+ onComponentChange: function(componentName) {
+ // show the component description
+ Dom.get('component').value = componentName;
+ var elComponentDesc = Dom.get('component_description');
+ elComponentDesc.innerHTML = '';
+ for (var i = 0, n = product.details.components.length; i < n; i++) {
+ var component = product.details.components[i];
+ if (component.name == componentName) {
+ elComponentDesc.innerHTML = component.description;
+ break;
+ }
+ }
+ Dom.removeClass(elComponentDesc, 'hidden');
+ },
+
+ onVersionChange: function(version) {
+ Dom.get('version').value = version;
+ },
+
+ onFileChange: function() {
+ // toggle ui enabled when a file is uploaded or cleared
+ var elFile = Dom.get('data');
+ var elReset = Dom.get('reset_data');
+ var elDescription = Dom.get('data_description');
+ var filename = bugForm._getFilename();
+ if (filename) {
+ elReset.disabled = false;
+ elDescription.value = filename;
+ elDescription.disabled = false;
+ } else {
+ elReset.disabled = true;
+ elDescription.value = '';
+ elDescription.disabled = true;
+ }
+ },
+
+ onFileClear: function() {
+ Dom.get('data').value = '';
+ this.onFileChange();
+ return false;
+ },
+
+ toggleOddEven: function() {
+ var rows = Dom.get('bugForm').getElementsByTagName('TR');
+ var doToggle = false;
+ for (var i = 0, n = rows.length; i < n; i++) {
+ if (doToggle) {
+ rows[i].className = rows[i].className == 'odd' ? 'even' : 'odd';
+ } else {
+ doToggle = rows[i].id == 'componentTR';
+ }
+ }
+ },
+
+ _getFilename: function() {
+ var filename = Dom.get('data').value;
+ if (!filename)
+ return '';
+ filename = filename.replace(/^.+[\\\/]/, '');
+ return filename;
+ },
+
+ _mandatoryMissing: function() {
+ var result = new Array();
+ for (var i = 0, n = this._mandatoryFields.length; i < n; i++ ) {
+ id = this._mandatoryFields[i];
+ el = Dom.get(id);
+
+ if (el.type.toString() == "checkbox") {
+ value = el.checked;
+ } else {
+ value = el.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ el.value = value;
+ }
+
+ if (value == '') {
+ Dom.addClass(id, 'missing');
+ result.push(id);
+ } else {
+ Dom.removeClass(id, 'missing');
+ }
+ }
+ return result;
+ },
+
+ validate: function() {
+
+ // check mandatory fields
+
+ var missing = bugForm._mandatoryMissing();
+ if (missing.length) {
+ var message = 'The following field' +
+ (missing.length == 1 ? ' is' : 's are') + ' required:\n\n';
+ for (var i = 0, n = missing.length; i < n; i++ ) {
+ var id = missing[i];
+ if (id == 'short_desc') message += ' Summary\n';
+ if (id == 'component_select') message += ' Component\n';
+ if (id == 'version_select') message += ' Version\n';
+ }
+ alert(message);
+ return false;
+ }
+
+ if (Dom.get('data').value && !Dom.get('data_description').value)
+ Dom.get('data_description').value = bugForm._getFilename();
+
+ Dom.get('submit').disabled = true;
+ Dom.get('submit').value = 'Submitting Bug...';
+
+ return true;
+ },
+
+ _initHelp: function(el) {
+ var help_id = el.getAttribute('helpid');
+ if (!el.panel) {
+ if (!el.id)
+ el.id = help_id + '_parent';
+ el.panel = new YAHOO.widget.Panel(
+ help_id,
+ {
+ width: "320px",
+ visible: false,
+ close: false,
+ context: [el.id, 'tl', 'tr', null, [5, 0]]
+ }
+ );
+ el.panel.render();
+ Dom.removeClass(help_id, 'hidden');
+ }
+ },
+
+ showHelp: function(el) {
+ this._initHelp(el);
+ if (this._visibleHelpPanel)
+ this._visibleHelpPanel.hide();
+ el.panel.show();
+ this._visibleHelpPanel = el.panel;
+ },
+
+ hideHelp: function(el) {
+ if (!el.panel)
+ return;
+ if (this._visibleHelpPanel)
+ this._visibleHelpPanel.hide();
+ el.panel.hide();
+ this._visibleHelpPanel = null;
+ }
+}
+
+function quoteMeta(value) {
+ return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+}
diff --git a/extensions/GuidedBugEntry/web/js/products.js b/extensions/GuidedBugEntry/web/js/products.js
new file mode 100644
index 000000000..dfc830d0f
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/js/products.js
@@ -0,0 +1,118 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+/* Product-specifc configuration for guided bug entry
+ *
+ * related: array of product names which will also be searched for duplicates
+ * version: function which returns a version (eg. detected from UserAgent)
+ * support: string which is displayed at the top of the duplicates page
+ * secgroup: the group to place confidential bugs into
+ * defaultComponent: the default compoent to select. Defaults to 'General'
+ * noComponentSelection: when true, the default component will always be
+ * used. Defaults to 'false';
+ * detectPlatform: when true the platform and op_sys will be set from the
+ * browser's user agent. when false, these will be set to All
+ */
+
+var products = {
+
+ "Firefox": {
+ related: [ "Core", "Toolkit" ],
+ version: function() {
+ var re = /Firefox\/(\d+)\.(\d+)/i;
+ var match = re.exec(navigator.userAgent);
+ if (match) {
+ var maj = match[1];
+ var min = match[2];
+ if (maj * 1 >= 5) {
+ return maj + " Branch";
+ } else {
+ return maj + "." + min + " Branch";
+ }
+ } else {
+ return false;
+ }
+ },
+ defaultComponent: "Untriaged",
+ noComponentSelection: true,
+ detectPlatform: true,
+ support:
+ 'If you are new to Firefox or Bugzilla, please consider checking ' +
+ '<a href="http://support.mozilla.com/">' +
+ '<img src="extensions/GuidedBugEntry/web/images/sumo.png" width="16" height="16" align="absmiddle">' +
+ ' <b>Firefox Help</b></a> instead of creating a bug.'
+ },
+
+ "Firefox for Android": {
+ related: [ "Core", "Toolkit" ],
+ detectPlatform: true,
+ support:
+ 'If you are new to Firefox or Bugzilla, please consider checking ' +
+ '<a href="http://support.mozilla.com/">' +
+ '<img src="extensions/GuidedBugEntry/web/images/sumo.png" width="16" height="16" align="absmiddle">' +
+ ' <b>Firefox Help</b></a> instead of creating a bug.'
+ },
+
+ "SeaMonkey": {
+ related: [ "Core", "Toolkit", "MailNews Core" ],
+ detectPlatform: true,
+ version: function() {
+ var re = /SeaMonkey\/(\d+)\.(\d+)/i;
+ var match = re.exec(navigator.userAgent);
+ if (match) {
+ var maj = match[1];
+ var min = match[2];
+ return "SeaMonkey " + maj + "." + min + " Branch";
+ } else {
+ return false;
+ }
+ }
+ },
+
+ "Camino": {
+ related: [ "Core", "Toolkit" ],
+ detectPlatform: true
+ },
+
+ "Core": {
+ detectPlatform: true
+ },
+
+ "Thunderbird": {
+ related: [ "Core", "Toolkit", "MailNews Core" ],
+ detectPlatform: true,
+ defaultComponent: "Untriaged",
+ componentFilter : function(components) {
+ var index = -1;
+ for (var i = 0, l = components.length; i < l; i++) {
+ if (components[i].name == 'General') {
+ index = i;
+ break;
+ }
+ }
+ if (index != -1) {
+ components.splice(index, 1);
+ }
+ return components;
+ }
+ },
+
+ "Penelope": {
+ related: [ "Core", "Toolkit", "MailNews Core" ]
+ },
+
+ "Bugzilla": {
+ support:
+ 'Please use <a href="http://landfill.bugzilla.org/">Bugzilla Landfill</a> to file "test bugs".'
+ },
+
+ "bugzilla.mozilla.org": {
+ related: [ "Bugzilla" ],
+ support:
+ 'Please use <a href="http://landfill.bugzilla.org/">Bugzilla Landfill</a> to file "test bugs".'
+ }
+}
diff --git a/extensions/GuidedBugEntry/web/style/guided.css b/extensions/GuidedBugEntry/web/style/guided.css
new file mode 100644
index 000000000..f06715eab
--- /dev/null
+++ b/extensions/GuidedBugEntry/web/style/guided.css
@@ -0,0 +1,237 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+/* global */
+
+#page_title {
+}
+
+#page_title h2 {
+ margin-bottom: 0px;
+}
+
+#page_title h3 {
+ margin-top: 0px;
+}
+
+.hidden {
+ display: none;
+}
+
+#yui-history-iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 1px;
+ height: 1px;
+ visibility: hidden;
+}
+
+.step {
+ margin-left: 20px;
+ margin-bottom: 25px;
+}
+
+#steps a img {
+ border: none;
+}
+
+#advanced {
+ margin-top: 50px;
+}
+
+#advanced img {
+ vertical-align: middle;
+}
+
+#advanced a {
+ cursor: pointer;
+}
+
+/* remove the shaded background from data_table header
+ it looks out of place */
+.yui-skin-sam .yui-dt th {
+ background: #f0f0f0;
+}
+
+/* products and other_products step */
+
+.exits {
+ width: 600px;
+ margin-bottom: 10px;
+ border: 1px solid #aaa;
+ border-radius: 5px;
+}
+
+.exits td {
+ padding: 5px;
+}
+
+.exits h2 {
+ margin: 0px;
+ font-size: 90%;
+}
+
+.exit_img {
+ width: 64px;
+ text-align: right;
+}
+
+.exit_text, .exit_text_last {
+ width: 100%;
+}
+
+.exit_text {
+ border-bottom: 1px dotted silver;
+}
+
+#prod_comp_search_main {
+ width: 400px;
+}
+
+#prod_comp_search_label {
+ margin-bottom: 1px;
+}
+
+#prod_comp_search_main li.yui-ac-highlight a {
+ text-decoration: none;
+ color: #FFFFFF;
+ display: block;
+}
+
+#products {
+ width: 600px;
+}
+
+#products td {
+ padding: 5px;
+ padding-bottom: 10px;
+}
+
+#products h2 {
+ margin-bottom: 0px;
+}
+
+#products p {
+ margin-top: 0px;
+}
+
+.product_img {
+ width: 64px;
+}
+
+#other_products .classification {
+ font-weight: bold;
+}
+
+#other_products .classification th {
+ font-size: large;
+}
+
+/* duplicates step */
+
+#dupes_summary {
+ width: 500px;
+}
+
+#dupes_list {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+#product_support {
+ border: 1px solid #dddddd;
+}
+
+/* bug form step */
+
+#bugForm {
+ width: 600px;
+ border: 4px solid #e0e0e0;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#bugForm th, #bugForm td {
+ padding: 5px;
+}
+
+#bugForm .even th, #bugForm .even td {
+ background: #e0e0e0;
+}
+
+#bugForm .label {
+ text-align: left;
+ font-weight: bold;
+ white-space: nowrap
+}
+
+#bugzilla-body #bugForm th {
+ vertical-align: middle;
+}
+
+#bugForm .textInput {
+ width: 450px;
+}
+
+#bugForm textarea {
+ font-family: Verdana, sans-serif;
+ font-size: small;
+ width: 590px;
+}
+
+#bugForm .mandatory_mark {
+ color: red;
+ font-size: 80%;
+}
+
+#bugForm .mandatory {
+}
+
+#bugForm .textInput[disabled] {
+ background: transparent;
+ border: 1px solid #dddddd;
+}
+
+#versionTD {
+ text-align: right;
+ white-space: nowrap
+}
+
+#component_select {
+ width: 450px;
+}
+
+#component_description {
+ padding: 5px;
+}
+
+#bugForm .missing {
+ border: 1px solid red;
+ box-shadow: 0px 0px 4px #ff0000;
+ -webkit-box-shadow: 0px 0px 4px #ff0000;
+ -moz-box-shadow: 0px 0px 4px #ff0000;
+}
+
+#submitTD {
+ text-align: right;
+}
+
+.help {
+ position: absolute;
+ background: #ffffff;
+ padding: 2px;
+ cursor: default;
+}
+
+.help-bad {
+ color: #990000;
+}
+
+.help-good {
+ color: #009900;
+}
diff --git a/extensions/Voting/disabled b/extensions/GuidedBugEntry/web/yui-history-iframe.txt
index e69de29bb..e69de29bb 100644
--- a/extensions/Voting/disabled
+++ b/extensions/GuidedBugEntry/web/yui-history-iframe.txt
diff --git a/extensions/InlineHistory/Config.pm b/extensions/InlineHistory/Config.pm
new file mode 100644
index 000000000..3834bd81d
--- /dev/null
+++ b/extensions/InlineHistory/Config.pm
@@ -0,0 +1,13 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::InlineHistory;
+use strict;
+
+use constant NAME => 'InlineHistory';
+
+__PACKAGE__->NAME;
diff --git a/extensions/InlineHistory/Extension.pm b/extensions/InlineHistory/Extension.pm
new file mode 100644
index 000000000..f761a9fbd
--- /dev/null
+++ b/extensions/InlineHistory/Extension.pm
@@ -0,0 +1,206 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::InlineHistory;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::User::Setting;
+use Bugzilla::Constants;
+use Bugzilla::Attachment;
+
+our $VERSION = '1.5';
+
+# don't show inline history for bugs with lots of changes
+use constant MAXIMUM_ACTIVITY_COUNT => 500;
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ return if $file ne 'bug/edit.html.tmpl';
+
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->dbh;
+ return unless $user->id && $user->settings->{'inline_history'}->{'value'} eq 'on';
+
+ # note: bug/edit.html.tmpl doesn't support multiple bugs
+ my $bug = exists $vars->{'bugs'} ? $vars->{'bugs'}[0] : $vars->{'bug'};
+ my $bug_id = $bug->id;
+
+ # build bug activity
+ my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id);
+ $activity = _add_duplicates($bug_id, $activity);
+
+ if (scalar @$activity > MAXIMUM_ACTIVITY_COUNT) {
+ $activity = [];
+ $vars->{'ih_activity'} = 0;
+ $vars->{'ih_activity_max'} = 1;
+ return;
+ }
+
+ # prime caches with objects already loaded
+ my %user_cache;
+ foreach my $comment (@{$bug->comments}) {
+ $user_cache{$comment->{author}->login} = $comment->{author};
+ }
+
+ my %attachment_cache;
+ foreach my $attachment (@{$bug->attachments}) {
+ $attachment_cache{$attachment->id} = $attachment;
+ }
+
+ # build a list of bugs we need to check visibility of, so we can check with a single query
+ my %visible_bug_ids;
+
+ # augment and tweak
+ foreach my $operation (@$activity) {
+ # make operation.who an object
+ $user_cache{$operation->{who}} ||= Bugzilla::User->new({ name => $operation->{who} });
+ $operation->{who} = $user_cache{$operation->{who}};
+
+ for (my $i = 0; $i < scalar(@{$operation->{changes}}); $i++) {
+ my $change = $operation->{changes}->[$i];
+
+ # make an attachment object
+ if ($change->{attachid}) {
+ $change->{attach} = $attachment_cache{$change->{attachid}};
+ }
+
+ # empty resolutions are displayed as --- by default
+ # make it explicit here to enable correct display of the change
+ if ($change->{fieldname} eq 'resolution') {
+ $change->{removed} = '---' if $change->{removed} eq '';
+ $change->{added} = '---' if $change->{added} eq '';
+ }
+
+ # make boolean fields true/false instead of 1/0
+ my ($table, $field) = ('bugs', $change->{fieldname});
+ if ($field =~ /^([^\.]+)\.(.+)$/) {
+ ($table, $field) = ($1, $2);
+ }
+ my $column = $dbh->bz_column_info($table, $field);
+ if ($column && $column->{TYPE} eq 'BOOLEAN') {
+ $change->{removed} = '';
+ $change->{added} = $change->{added} ? 'true' : 'false';
+ }
+
+ my $field_obj;
+ if ($change->{fieldname} =~ /^cf_/) {
+ $field_obj = Bugzilla::Field->new({ name => $change->{fieldname}, cache => 1 });
+ }
+
+ # identify buglist changes
+ if ($change->{fieldname} eq 'blocked' ||
+ $change->{fieldname} eq 'dependson' ||
+ $change->{fieldname} eq 'dupe' ||
+ ($field_obj && $field_obj->type == FIELD_TYPE_BUG_ID)
+ ) {
+ $change->{buglist} = 1;
+ foreach my $what (qw(removed added)) {
+ my @buglist = split(/[\s,]+/, $change->{$what});
+ foreach my $id (@buglist) {
+ if ($id && $id =~ /^\d+$/) {
+ $visible_bug_ids{$id} = 1;
+ }
+ }
+ }
+ }
+
+ # split multiple flag changes (must be processed last)
+ if ($change->{fieldname} eq 'flagtypes.name') {
+ my @added = split(/, /, $change->{added});
+ my @removed = split(/, /, $change->{removed});
+ next if scalar(@added) <= 1 && scalar(@removed) <= 1;
+ # remove current change
+ splice(@{$operation->{changes}}, $i, 1);
+ # restructure into added/removed for each flag
+ my %flags;
+ foreach my $added (@added) {
+ my ($value, $name) = $added =~ /^((.+).)$/;
+ $flags{$name}{added} = $value;
+ $flags{$name}{removed} |= '';
+ }
+ foreach my $removed (@removed) {
+ my ($value, $name) = $removed =~ /^((.+).)$/;
+ $flags{$name}{added} |= '';
+ $flags{$name}{removed} = $value;
+ }
+ # clone current change, modify and insert
+ foreach my $flag (sort keys %flags) {
+ my $flag_change = {};
+ foreach my $key (keys %$change) {
+ $flag_change->{$key} = $change->{$key};
+ }
+ $flag_change->{removed} = $flags{$flag}{removed};
+ $flag_change->{added} = $flags{$flag}{added};
+ splice(@{$operation->{changes}}, $i, 0, $flag_change);
+ }
+ $i--;
+ }
+ }
+ }
+
+ $user->visible_bugs([keys %visible_bug_ids]);
+
+ $vars->{'ih_activity'} = $activity;
+}
+
+sub _add_duplicates {
+ # insert 'is a dupe of this bug' comment to allow js to display
+ # as activity
+
+ my ($bug_id, $activity) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ my $sth = $dbh->prepare("
+ SELECT profiles.login_name, " .
+ $dbh->sql_date_format('bug_when', '%Y.%m.%d %H:%i:%s') . ",
+ extra_data,
+ thetext
+ FROM longdescs
+ INNER JOIN profiles ON profiles.userid = longdescs.who
+ WHERE bug_id = ?
+ AND (
+ type = ?
+ OR thetext LIKE '%has been marked as a duplicate of this%'
+ )
+ ORDER BY bug_when
+ ");
+ $sth->execute($bug_id, CMT_HAS_DUPE);
+
+ while (my($who, $when, $dupe_id, $the_text) = $sth->fetchrow_array) {
+ if (!$dupe_id) {
+ next unless $the_text =~ / (\d+) has been marked as a duplicate of this/;
+ $dupe_id = $1;
+ }
+ my $entry = {
+ 'when' => $when,
+ 'who' => $who,
+ 'changes' => [
+ {
+ 'removed' => '',
+ 'added' => $dupe_id,
+ 'attachid' => undef,
+ 'fieldname' => 'dupe',
+ 'dupe' => 1,
+ }
+ ],
+ };
+ push @$activity, $entry;
+ }
+
+ return [ sort { $a->{when} cmp $b->{when} } @$activity ];
+}
+
+sub install_before_final_checks {
+ my ($self, $args) = @_;
+ add_setting('inline_history', ['on', 'off'], 'off');
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/InlineHistory/README b/extensions/InlineHistory/README
new file mode 100644
index 000000000..f5aaf163f
--- /dev/null
+++ b/extensions/InlineHistory/README
@@ -0,0 +1,10 @@
+InlineHistory inserts bug activity inline with the comments when viewing a bug.
+It was derived from the Bugzilla Tweaks Addon by Ehasn Akhgari.
+
+For technical and performance reasons it is only available to logged in users,
+and is enabled by a User Preference.
+
+It works with an unmodified install of Bugzilla 4.0 and 4.2.
+
+If you have modified your show_bug template, the javascript in
+web/inline-history.js may need to be updated to suit your installation.
diff --git a/extensions/InlineHistory/template/en/default/hook/bug/comments-aftercomments.html.tmpl b/extensions/InlineHistory/template/en/default/hook/bug/comments-aftercomments.html.tmpl
new file mode 100644
index 000000000..1c47fd21c
--- /dev/null
+++ b/extensions/InlineHistory/template/en/default/hook/bug/comments-aftercomments.html.tmpl
@@ -0,0 +1,152 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS ih_activity %]
+[%# this div exists to allow bugzilla-tweaks to detect when we're active %]
+<div id="inline-history-ext"></div>
+
+<script>
+ var ih_activity = new Array();
+ var ih_activity_flags = new Array();
+ var ih_activity_sort_order = '[% user.settings.comment_sort_order.value FILTER js %]';
+ [% FOREACH operation = ih_activity %]
+ var html = '';
+ [% has_cc = 0 %]
+ [% has_flag = 0 %]
+ [% changer_identity = operation.who.identity %]
+ [% changer_login = operation.who.login %]
+ [% change_date = operation.when FILTER time %]
+
+ [% FOREACH change = operation.changes %]
+ [%# track flag changes %]
+ [% IF change.fieldname == 'flagtypes.name' && change.added != '' %]
+ var item = new Array(5);
+ item[0] = '[% changer_login FILTER js %]';
+ item[1] = '[% change_date FILTER js %]';
+ item[2] = '[% change.attachid FILTER js %]';
+ item[3] = '[% change.added FILTER js %]';
+ item[4] = '[% changer_identity FILTER js %]';
+ ih_activity_flags.push(item);
+ [% has_flag = 1 %]
+ [% END %]
+
+ [%# wrap CC changes in a span for toggling visibility %]
+ [% IF change.fieldname == 'cc' %]
+ html += '<span class="ih_cc">';
+ [% has_cc = 1 %]
+ [% END %]
+
+ [%# make attachment changes better %]
+ [% IF change.attachid %]
+ html += '<a '
+ + 'href="attachment.cgi?id=[% change.attachid FILTER none %]&amp;action=edit" '
+ + 'title="[% change.attach.description FILTER html FILTER js %]" '
+ + 'class="[% "bz_obsolete" IF change.attach.isobsolete %]"'
+ + '>Attachment #[% change.attachid FILTER none %]</a> - ';
+ [% END %]
+
+ [%# buglists need to be displayed differently, as we shouldn't use strike-out %]
+ [% IF change.buglist %]
+ [% IF change.dupe %]
+ [% label = 'Duplicate of this ' _ terms.bug %]
+ [% ELSE %]
+ [% label = field_descs.${change.fieldname} %]
+ [% END %]
+ [% IF change.added != '' %]
+ html += '[% label FILTER js %]: ';
+ [% PROCESS add_change value = change.added %]
+ [% END %]
+ [% IF change.removed != '' %]
+ [% "html += '<br>';" IF change.added != '' %]
+ html += 'No longer [% label FILTER lcfirst FILTER js %]: ';
+ [% PROCESS add_change value = change.removed %]
+ [% END %]
+ [% ELSE %]
+ [% IF change.fieldname == 'longdescs.isprivate' %]
+ [%# reference the comment that was made private/public in the field label %]
+ html += '<a href="#c[% change.comment.count FILTER js %]">'
+ + 'Comment [% change.comment.count FILTER js %]</a> is private: ';
+ [% ELSE %]
+ [%# normal label %]
+ html += '[% field_descs.${change.fieldname} FILTER js %]: ';
+ [% END %]
+ [% IF change.removed != '' %]
+ [% IF change.added == '' %]
+ html += '<span class="ih_deleted">';
+ [% END %]
+ [% PROCESS add_change value = change.removed %]
+ [% IF change.added == '' %]
+ html += '</span>';
+ [% ELSE %]
+ html += ' &rarr; ';
+ [% END %]
+ [% END %]
+ [% PROCESS add_change value = change.added %]
+ [% END %]
+ [% "html += '<br>';" UNLESS loop.last %]
+
+ [% IF change.fieldname == 'cc' %]
+ html += '</span>';
+ [% END %]
+ [% END %]
+
+ [% changer_id = operation.who.id %]
+ [% UNLESS user_cache.$changer_id %]
+ [% user_cache.$changer_id = BLOCK %]
+ [% INCLUDE global/user.html.tmpl who = operation.who %]
+ [% END %]
+ [% END %]
+
+ var item = new Array(7);
+ item[0] = '[% changer_login FILTER js %]';
+ item[1] = '[% change_date FILTER js %]';
+ item[2] = html;
+ item[3] = '<div class="bz_comment_head">'
+ + '<span class="bz_comment_user">'
+ + '[% user_cache.$changer_id FILTER js %]'
+ + '</span>'
+ + '<span class="bz_comment_time"> ' + item[1] + ' </span>'
+ + '</div>';
+ item[4] = [% IF has_cc && (operation.changes.size == 1) %]true[% ELSE %]false[% END %];
+ item[5] = [% IF change.dupe %][% change.added FILTER js %][% ELSE %]0[% END %];
+ item[6] = [% IF has_flag %]true[% ELSE %]false[% END %];
+ ih_activity[[% loop.index %]] = item;
+ [% END %]
+ inline_history.init();
+</script>
+
+[% BLOCK add_change %]
+ html += '[%~%]
+ [% IF change.fieldname == 'estimated_time' ||
+ change.fieldname == 'remaining_time' ||
+ change.fieldname == 'work_time' %]
+ [% PROCESS formattimeunit time_unit = value FILTER html FILTER js %]
+ [% ELSIF change.buglist %]
+ [% value FILTER bug_list_link FILTER js %]
+ [% ELSIF change.fieldname == 'bug_file_loc' %]
+ [%~%]<a href="[% value FILTER html FILTER js %]" target="_blank"
+ [%~ ' onclick="return inline_history.confirmUnsafeUrl(this.href)"'
+ UNLESS is_safe_url(value) %]>
+ [%~%][% value FILTER html FILTER js %]</a>
+ [% ELSIF change.fieldname == 'see_also' %]
+ [% FOREACH see_also = value.split(', ') %]
+ [%~%]<a href="[% see_also FILTER html FILTER js %]" target="_blank">
+ [%~%][% see_also FILTER html FILTER js %]</a>
+ [%- ", " IF NOT loop.last %]
+ [% END %]
+ [% ELSIF change.fieldname == 'assigned_to' ||
+ change.fieldname == 'reporter' ||
+ change.fieldname == 'qa_contact' ||
+ change.fieldname == 'cc' ||
+ change.fieldname == 'flagtypes.name' %]
+ [% value FILTER email FILTER js %]
+ [% ELSE %]
+ [% value FILTER html FILTER js %]
+ [% END %]
+ [%~ %]';
+[% END %]
diff --git a/extensions/InlineHistory/template/en/default/hook/bug/comments-comment_banner.html.tmpl b/extensions/InlineHistory/template/en/default/hook/bug/comments-comment_banner.html.tmpl
new file mode 100644
index 000000000..133005f4f
--- /dev/null
+++ b/extensions/InlineHistory/template/en/default/hook/bug/comments-comment_banner.html.tmpl
@@ -0,0 +1,13 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF ih_activity_max %]
+<p>
+ <i>This [% terms.bug %] contains too many changes to be displayed inline.</i>
+</p>
+[% END %]
diff --git a/extensions/InlineHistory/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/InlineHistory/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..7e54b8380
--- /dev/null
+++ b/extensions/InlineHistory/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.id && user.settings.inline_history.value == "on" %]
+ [% style_urls.push('extensions/InlineHistory/web/style.css') %]
+ [% javascript_urls.push('extensions/InlineHistory/web/inline-history.js') %]
+[% END %]
diff --git a/extensions/InlineHistory/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/InlineHistory/template/en/default/hook/global/setting-descs-settings.none.tmpl
new file mode 100644
index 000000000..e1ff4c0f6
--- /dev/null
+++ b/extensions/InlineHistory/template/en/default/hook/global/setting-descs-settings.none.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ setting_descs.inline_history = "When viewing a $terms.bug, show all $terms.bug activity",
+%]
diff --git a/extensions/InlineHistory/web/inline-history.js b/extensions/InlineHistory/web/inline-history.js
new file mode 100644
index 000000000..0d38edf7f
--- /dev/null
+++ b/extensions/InlineHistory/web/inline-history.js
@@ -0,0 +1,385 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+var inline_history = {
+ _ccDivs: null,
+ _hasAttachmentFlags: false,
+ _hasBugFlags: false,
+
+ init: function() {
+ Dom = YAHOO.util.Dom;
+
+ // remove 'has been marked as a duplicate of this bug' comments
+ var reDuplicate = /^\*\*\* \S+ \d+ has been marked as a duplicate of this/;
+ var reBugId = /show_bug\.cgi\?id=(\d+)/;
+ var comments = Dom.getElementsByClassName("bz_comment", 'div', 'comments');
+ for (var i = 1, il = comments.length; i < il; i++) {
+ var textDiv = Dom.getElementsByClassName('bz_comment_text', 'pre', comments[i]);
+ if (textDiv) {
+ var match = reDuplicate.exec(textDiv[0].textContent || textDiv[0].innerText);
+ if (match) {
+ // grab the comment and bug number from the element
+ var comment = comments[i];
+ var number = comment.id.substr(1);
+ var time = this.trim(Dom.getElementsByClassName('bz_comment_time', 'span', comment)[0].innerHTML);
+ var dupeId = 0;
+ match = reBugId.exec(Dom.get('comment_text_' + number).innerHTML);
+ if (match)
+ dupeId = match[1];
+ // remove the element
+ comment.parentNode.removeChild(comment);
+ // update the html for the history item to include the comment number
+ if (dupeId == 0)
+ continue;
+ for (var j = 0, jl = ih_activity.length; j < jl; j++) {
+ var item = ih_activity[j];
+ if (item[5] == dupeId && item[1] == time) {
+ // insert comment number and link into the header
+ item[3] = item[3].substr(0, item[3].length - 6) // remove trailing </div>
+ // add comment number
+ + '<span class="bz_comment_number" id="c' + number + '">'
+ + '<a href="#c' + number + '">Comment ' + number + '</a>'
+ + '</span>'
+ + '</div>';
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // ensure new items are placed immediately after the last comment
+ var commentDivs = Dom.getElementsByClassName('bz_comment', 'div', 'comments');
+ if (!commentDivs.length) return;
+ var lastCommentDiv = commentDivs[commentDivs.length - 1];
+
+ // insert activity into the correct location
+ var commentTimes = Dom.getElementsByClassName('bz_comment_time', 'span', 'comments');
+ for (var i = 0, il = ih_activity.length; i < il; i++) {
+ var item = ih_activity[i];
+ // item[0] : who
+ // item[1] : when
+ // item[2] : change html
+ // item[3] : header html
+ // item[4] : bool; cc-only
+ // item[5] : int; dupe bug id (or 0)
+ // item[6] : bool; is flag
+ var user = item[0];
+ var time = item[1];
+
+ var reachedEnd = false;
+ var start_index = ih_activity_sort_order == 'newest_to_oldest_desc_first' ? 1 : 0;
+ for (var j = start_index, jl = commentTimes.length; j < jl; j++) {
+ var commentHead = commentTimes[j].parentNode;
+ var mainUser = Dom.getElementsByClassName('email', 'a', commentHead)[0].href.substr(7);
+ var text = commentTimes[j].textContent || commentTimes[j].innerText;
+ var mainTime = this.trim(text);
+
+ if (ih_activity_sort_order == 'oldest_to_newest' ? time > mainTime : time < mainTime) {
+ if (j < commentTimes.length - 1) {
+ continue;
+ } else {
+ reachedEnd = true;
+ }
+ }
+
+ var inline = (mainUser == user && time == mainTime);
+ var currentDiv = document.createElement("div");
+
+ // place ih_cc class on parent container if it's the only child
+ var containerClass = '';
+ if (item[4]) {
+ item[2] = item[2].replace('"ih_cc"', '""');
+ containerClass = 'ih_cc';
+ }
+
+ if (inline) {
+ // assume that the change was made by the same user
+ commentHead.parentNode.appendChild(currentDiv);
+ currentDiv.innerHTML = item[2];
+ Dom.addClass(currentDiv, 'ih_inlinehistory');
+ Dom.addClass(currentDiv, containerClass);
+ if (item[6])
+ this.setFlagChangeID(item, commentHead.parentNode.id);
+
+ } else {
+ // the change was made by another user
+ if (!reachedEnd) {
+ var parentDiv = commentHead.parentNode;
+ var previous = this.previousElementSibling(parentDiv);
+ if (previous && previous.className.indexOf("ih_history") >= 0) {
+ currentDiv = this.previousElementSibling(parentDiv);
+ } else {
+ parentDiv.parentNode.insertBefore(currentDiv, parentDiv);
+ }
+ } else {
+ var parentDiv = commentHead.parentNode;
+ var next = this.nextElementSibling(parentDiv);
+ if (next && next.className.indexOf("ih_history") >= 0) {
+ currentDiv = this.nextElementSibling(parentDiv);
+ } else {
+ lastCommentDiv.parentNode.insertBefore(currentDiv, lastCommentDiv.nextSibling);
+ }
+ }
+
+ var itemHtml = '<div class="ih_history_item ' + containerClass + '" '
+ + 'id="h' + i + '">'
+ + item[3] + item[2]
+ + '</div>';
+
+ if (ih_activity_sort_order == 'oldest_to_newest') {
+ currentDiv.innerHTML = currentDiv.innerHTML + itemHtml;
+ } else {
+ currentDiv.innerHTML = itemHtml + currentDiv.innerHTML;
+ }
+ currentDiv.setAttribute("class", "bz_comment ih_history");
+ if (item[6])
+ this.setFlagChangeID(item, 'h' + i);
+ }
+ break;
+ }
+ }
+
+ // find comment blocks which only contain cc changes, shift the ih_cc
+ var historyDivs = Dom.getElementsByClassName('ih_history', 'div', 'comments');
+ for (var i = 0, il = historyDivs.length; i < il; i++) {
+ var historyDiv = historyDivs[i];
+ var itemDivs = Dom.getElementsByClassName('ih_history_item', 'div', historyDiv);
+ var ccOnly = true;
+ for (var j = 0, jl = itemDivs.length; j < jl; j++) {
+ if (!Dom.hasClass(itemDivs[j], 'ih_cc')) {
+ ccOnly = false;
+ break;
+ }
+ }
+ if (ccOnly) {
+ for (var j = 0, jl = itemDivs.length; j < jl; j++) {
+ Dom.removeClass(itemDivs[j], 'ih_cc');
+ }
+ Dom.addClass(historyDiv, 'ih_cc');
+ }
+ }
+
+ if (this._hasAttachmentFlags)
+ this.linkAttachmentFlags();
+ if (this._hasBugFlags)
+ this.linkBugFlags();
+
+ ih_activity = undefined;
+ ih_activity_flags = undefined;
+
+ this._ccDivs = Dom.getElementsByClassName('ih_cc', '', 'comments');
+ this.hideCC();
+ YAHOO.util.Event.onDOMReady(this.addCCtoggler);
+ },
+
+ setFlagChangeID: function(changeItem, id) {
+ // put the ID for the change into ih_activity_flags
+ for (var i = 0, il = ih_activity_flags.length; i < il; i++) {
+ var flagItem = ih_activity_flags[i];
+ // flagItem[0] : who.login
+ // flagItem[1] : when
+ // flagItem[2] : attach id
+ // flagItem[3] : flag
+ // flagItem[4] : who.identity
+ // flagItem[5] : change div id
+ if (flagItem[0] == changeItem[0] && flagItem[1] == changeItem[1]) {
+ // store the div
+ flagItem[5] = id;
+ // tag that we have flags to process
+ if (flagItem[2]) {
+ this._hasAttachmentFlags = true;
+ } else {
+ this._hasBugFlags = true;
+ }
+ // don't break as there may be multiple flag changes at once
+ }
+ }
+ },
+
+ linkAttachmentFlags: function() {
+ var rows = Dom.get('attachment_table').getElementsByTagName('tr');
+ for (var i = 0, il = rows.length; i < il; i++) {
+
+ // deal with attachments with flags only
+ var tr = rows[i];
+ if (!tr.id || tr.id == 'a0')
+ continue;
+ var attachFlagTd = Dom.getElementsByClassName('bz_attach_flags', 'td', tr);
+ if (attachFlagTd.length == 0)
+ continue;
+ attachFlagTd = attachFlagTd[0];
+
+ // get the attachment id
+ var attachId = 0;
+ var anchors = tr.getElementsByTagName('a');
+ for (var j = 0, jl = anchors.length; j < jl; j++) {
+ var match = anchors[j].href.match(/attachment\.cgi\?id=(\d+)/);
+ if (match) {
+ attachId = match[1];
+ break;
+ }
+ }
+ if (!attachId)
+ continue;
+
+ var html = '';
+
+ // there may be multiple flags, split by <br>
+ var attachFlags = attachFlagTd.innerHTML.split('<br>');
+ for (var j = 0, jl = attachFlags.length; j < jl; j++) {
+ var match = attachFlags[j].match(/^\s*(<span.+\/span>):([^\?\-\+]+[\?\-\+])([\s\S]*)/);
+ if (!match) continue;
+ var setterSpan = match[1];
+ var flag = this.trim(match[2].replace('\u2011', '-', 'g'));
+ var requestee = this.trim(match[3]);
+ var requesteeLogin = '';
+
+ match = setterSpan.match(/title="([^"]+)"/);
+ if (!match) continue;
+ var setterIdentity = this.htmlDecode(match[1]);
+
+ if (requestee) {
+ match = requestee.match(/title="([^"]+)"/);
+ if (!match) continue;
+ requesteeLogin = this.htmlDecode(match[1]);
+ match = requesteeLogin.match(/<([^>]+)>/);
+ if (match)
+ requesteeLogin = match[1];
+ }
+
+ var flagValue = requestee ? flag + '(' + requesteeLogin + ')' : flag;
+ // find the id for this change
+ var found = false;
+ for (var k = 0, kl = ih_activity_flags.length; k < kl; k++) {
+ flagItem = ih_activity_flags[k];
+ if (
+ flagItem[2] == attachId
+ && flagItem[3] == flagValue
+ && flagItem[4] == setterIdentity
+ ) {
+ html +=
+ setterSpan + ': '
+ + '<a href="#' + flagItem[5] + '">' + flag + '</a> '
+ + requestee + '<br>';
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // something went wrong, insert the flag unlinked
+ html += attachFlags[j] + '<br>';
+ }
+ }
+
+ if (html)
+ attachFlagTd.innerHTML = html;
+ }
+ },
+
+ linkBugFlags: function() {
+ var flags = Dom.get('flags');
+ if (!flags) return;
+ var rows = flags.getElementsByTagName('tr');
+ for (var i = 0, il = rows.length; i < il; i++) {
+ var cells = rows[i].getElementsByTagName('td');
+ if (!cells[1]) continue;
+
+ var match = cells[0].innerHTML.match(/title="([^"]+)"/);
+ if (!match) continue;
+ var setterIdentity = this.htmlDecode(match[1]);
+
+ var flagValue = cells[2].getElementsByTagName('select');
+ if (!flagValue.length) continue;
+ flagValue = flagValue[0].value;
+
+ var flagLabel = cells[1].getElementsByTagName('label');
+ if (!flagLabel.length) continue;
+ flagLabel = flagLabel[0];
+ var flagName = this.trim(flagLabel.innerHTML).replace('\u2011', '-', 'g');
+
+ for (var j = 0, jl = ih_activity_flags.length; j < jl; j++) {
+ flagItem = ih_activity_flags[j];
+ if (
+ !flagItem[2]
+ && flagItem[3] == flagName + flagValue
+ && flagItem[4] == setterIdentity
+ ) {
+ flagLabel.innerHTML =
+ '<a href="#' + flagItem[5] + '">' + flagName + '</a>';
+ break;
+ }
+ }
+ }
+ },
+
+ hideCC: function() {
+ Dom.addClass(this._ccDivs, 'ih_hidden');
+ },
+
+ showCC: function() {
+ Dom.removeClass(this._ccDivs, 'ih_hidden');
+ },
+
+ addCCtoggler: function() {
+ var ul = Dom.getElementsByClassName('bz_collapse_expand_comments');
+ if (ul.length == 0)
+ return;
+ ul = ul[0];
+ var a = document.createElement('a');
+ a.href = 'javascript:void(0)';
+ a.id = 'ih_toggle_cc';
+ YAHOO.util.Event.addListener(a, 'click', function(e) {
+ if (Dom.get('ih_toggle_cc').innerHTML == 'Show CC Changes') {
+ a.innerHTML = 'Hide CC Changes';
+ inline_history.showCC();
+ } else {
+ a.innerHTML = 'Show CC Changes';
+ inline_history.hideCC();
+ }
+ });
+ a.innerHTML = 'Show CC Changes';
+ var li = document.createElement('li');
+ li.appendChild(a);
+ ul.appendChild(li);
+ },
+
+ confirmUnsafeUrl: function(url) {
+ return confirm(
+ 'This is considered an unsafe URL and could possibly be harmful.\n'
+ + 'The full URL is:\n\n' + url + '\n\nContinue?');
+ },
+
+ previousElementSibling: function(el) {
+ if (el.previousElementSibling)
+ return el.previousElementSibling;
+ while (el = el.previousSibling) {
+ if (el.nodeType == 1)
+ return el;
+ }
+ },
+
+ nextElementSibling: function(el) {
+ if (el.nextElementSibling)
+ return el.nextElementSibling;
+ while (el = el.nextSibling) {
+ if (el.nodeType == 1)
+ return el;
+ }
+ },
+
+ htmlDecode: function(v) {
+ if (!v.match(/&/)) return v;
+ var e = document.createElement('textarea');
+ e.innerHTML = v;
+ return e.value;
+ },
+
+ trim: function(s) {
+ return s.replace(/^\s+|\s+$/g, '');
+ }
+}
diff --git a/extensions/InlineHistory/web/style.css b/extensions/InlineHistory/web/style.css
new file mode 100644
index 000000000..af76eba82
--- /dev/null
+++ b/extensions/InlineHistory/web/style.css
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+.ih_history {
+ background: none !important;
+ color: #444;
+}
+
+.ih_inlinehistory {
+ font-weight: normal;
+ font-size: small;
+ color: #444;
+ border-top: 1px dotted #C8C8BA;
+ padding-top: 5px;
+}
+
+.bz_comment.ih_history {
+ padding: 5px 5px 0px 5px
+}
+
+.ih_history_item {
+ margin-bottom: 5px;
+}
+
+.ih_hidden {
+ display: none;
+}
+
+.ih_deleted {
+ text-decoration: line-through;
+}
diff --git a/extensions/LastResolved/Config.pm b/extensions/LastResolved/Config.pm
new file mode 100644
index 000000000..f763167e2
--- /dev/null
+++ b/extensions/LastResolved/Config.pm
@@ -0,0 +1,20 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::LastResolved;
+
+use strict;
+
+use constant NAME => 'LastResolved';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/LastResolved/Extension.pm b/extensions/LastResolved/Extension.pm
new file mode 100644
index 000000000..3627330c2
--- /dev/null
+++ b/extensions/LastResolved/Extension.pm
@@ -0,0 +1,112 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::LastResolved;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Bug qw(LogActivityEntry);
+use Bugzilla::Util qw(format_time);
+use Bugzilla::Constants;
+use Bugzilla::Field;
+use Bugzilla::Install::Util qw(indicate_progress);
+
+our $VERSION = '0.01';
+
+sub install_update_db {
+ my ($self, $args) = @_;
+ my $last_resolved = Bugzilla::Field->new({'name' => 'cf_last_resolved'});
+ if (!$last_resolved) {
+ Bugzilla::Field->create({
+ name => 'cf_last_resolved',
+ description => 'Last Resolved',
+ type => FIELD_TYPE_DATETIME,
+ mailhead => 0,
+ enter_bug => 0,
+ obsolete => 0,
+ custom => 1,
+ buglist => 1,
+ });
+ _migrate_last_resolved();
+ }
+}
+
+sub _migrate_last_resolved {
+ my $dbh = Bugzilla->dbh;
+ my $field_id = get_field_id('bug_status');
+ my $resolved_activity = $dbh->selectall_arrayref(
+ "SELECT bugs_activity.bug_id, bugs_activity.bug_when, bugs_activity.who
+ FROM bugs_activity
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.added = 'RESOLVED'
+ ORDER BY bugs_activity.bug_when",
+ undef, $field_id);
+
+ my $count = 1;
+ my $total = scalar @$resolved_activity;
+ my %current_last_resolved;
+ foreach my $activity (@$resolved_activity) {
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ my ($id, $new, $who) = @$activity;
+ my $old = $current_last_resolved{$id} ? $current_last_resolved{$id} : "";
+ $dbh->do("UPDATE bugs SET cf_last_resolved = ? WHERE bug_id = ?", undef, $new, $id);
+ LogActivityEntry($id, 'cf_last_resolved', $old, $new, $who, $new);
+ $current_last_resolved{$id} = $new;
+ }
+}
+
+sub active_custom_fields {
+ my ($self, $args) = @_;
+ my $fields = $args->{'fields'};
+ my @tmp_fields = grep($_->name ne 'cf_last_resolved', @$$fields);
+ $$fields = \@tmp_fields;
+}
+
+sub bug_end_of_update {
+ my ($self, $args) = @_;
+ my $dbh = Bugzilla->dbh;
+ my ($bug, $old_bug, $timestamp, $changes) =
+ @$args{qw(bug old_bug timestamp changes)};
+ if ($changes->{'bug_status'}) {
+ # If the bug has been resolved then update the cf_last_resolved
+ # value to the current timestamp if cf_last_resolved exists
+ if ($bug->bug_status eq 'RESOLVED') {
+ $dbh->do("UPDATE bugs SET cf_last_resolved = ? WHERE bug_id = ?",
+ undef, $timestamp, $bug->id);
+ my $old_value = $bug->cf_last_resolved || '';
+ LogActivityEntry($bug->id, 'cf_last_resolved', $old_value,
+ $timestamp, Bugzilla->user->id, $timestamp);
+ }
+ }
+}
+
+sub bug_fields {
+ my ($self, $args) = @_;
+ my $fields = $args->{'fields'};
+ push (@$fields, 'cf_last_resolved')
+}
+
+sub object_columns {
+ my ($self, $args) = @_;
+ my ($class, $columns) = @$args{qw(class columns)};
+ if ($class->isa('Bugzilla::Bug')) {
+ push(@$columns, 'cf_last_resolved');
+ }
+}
+
+sub buglist_columns {
+ my ($self, $args) = @_;
+ my $columns = $args->{columns};
+ $columns->{'cf_last_resolved'} = {
+ name => 'bugs.cf_last_resolved',
+ title => 'Last Resolved',
+ };
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/LastResolved/template/en/default/hook/global/field-descs-end.none.tmpl b/extensions/LastResolved/template/en/default/hook/global/field-descs-end.none.tmpl
new file mode 100644
index 000000000..4457ccd9b
--- /dev/null
+++ b/extensions/LastResolved/template/en/default/hook/global/field-descs-end.none.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF in_template_var %]
+ [% vars.field_descs.cf_last_resolved = "Last Resolved" %]
+[% END %]
diff --git a/extensions/LimitedEmail/Config.pm b/extensions/LimitedEmail/Config.pm
new file mode 100644
index 000000000..ea05f363c
--- /dev/null
+++ b/extensions/LimitedEmail/Config.pm
@@ -0,0 +1,22 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::LimitedEmail;
+
+use strict;
+use constant NAME => 'LimitedEmail';
+use constant REQUIRED_MODULES => [ ];
+use constant OPTIONAL_MODULES => [ ];
+
+use constant FILTERS => [
+ qr/^(?:glob|dkl|justdave|shyam)\@mozilla\.com$/i,
+ qr/^byron\.jones\@gmail\.com$/i,
+ qr/^gerv\@mozilla\.org$/i,
+ qr/^reed\@reedloden\.com$/i,
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/LimitedEmail/Extension.pm b/extensions/LimitedEmail/Extension.pm
new file mode 100644
index 000000000..35cc83567
--- /dev/null
+++ b/extensions/LimitedEmail/Extension.pm
@@ -0,0 +1,62 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::LimitedEmail;
+use strict;
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '2';
+
+use FileHandle;
+use Date::Format;
+use Encode qw(encode_utf8);
+use Bugzilla::Constants qw(bz_locations);
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+ my $email = $args->{email};
+ my $header = $email->{header};
+ return if $header->header('to') eq '';
+
+ my $blocked = '';
+ if (!deliver_to($header->header('to'))) {
+ $blocked = $header->header('to');
+ $header->header_set(to => '');
+ }
+
+ my $log_filename = bz_locations->{'datadir'} . '/mail.log';
+ my $fh = FileHandle->new(">>$log_filename");
+ if ($fh) {
+ print $fh encode_utf8(sprintf(
+ "[%s] %s%s %s : %s\n",
+ time2str('%D %T', time),
+ ($blocked eq '' ? '' : '(blocked) '),
+ ($blocked eq '' ? $header->header('to') : $blocked),
+ $header->header('X-Bugzilla-Reason') || '-',
+ $header->header('subject')
+ ));
+ $fh->close();
+ }
+}
+
+sub deliver_to {
+ my $email = address_of(shift);
+ my $ra_filters = Bugzilla::Extension::LimitedEmail::FILTERS;
+ foreach my $re (@$ra_filters) {
+ if ($email =~ $re) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub address_of {
+ my $email = shift;
+ return $email =~ /<([^>]+)>/ ? $1 : $email;
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/LimitedEmail/disabled b/extensions/LimitedEmail/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/LimitedEmail/disabled
diff --git a/extensions/MozProjectReview/Config.pm b/extensions/MozProjectReview/Config.pm
new file mode 100644
index 000000000..5a9d2b730
--- /dev/null
+++ b/extensions/MozProjectReview/Config.pm
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::MozProjectReview;
+
+use strict;
+
+use constant NAME => 'MozProjectReview';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/MozProjectReview/Extension.pm b/extensions/MozProjectReview/Extension.pm
new file mode 100644
index 000000000..31836700f
--- /dev/null
+++ b/extensions/MozProjectReview/Extension.pm
@@ -0,0 +1,305 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::MozProjectReview;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::User;
+use Bugzilla::Group;
+use Bugzilla::Error;
+use Bugzilla::Constants;
+use Bugzilla::FlagType;
+
+our $VERSION = '0.01';
+
+sub post_bug_after_creation {
+ my ($self, $args) = @_;
+ my $vars = $args->{vars};
+ my $bug = $vars->{bug};
+
+ my $user = Bugzilla->user;
+ my $params = Bugzilla->input_params;
+ my $template = Bugzilla->template;
+
+ return if !($params->{format}
+ && $params->{format} eq 'moz-project-review'
+ && $bug->component eq 'Project Review');
+
+ my $error_mode_cache = Bugzilla->error_mode;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+
+ # do a match if applicable
+ Bugzilla::User::match_field({
+ 'legal_cc' => { 'type' => 'multi' }
+ });
+
+ my ($do_sec_review, $do_legal, $do_finance, $do_privacy_vendor,
+ $do_data_safety, $do_privacy_tech, $do_privacy_policy);
+
+ # Logic section which dictates which bugs are created. This should be
+ # similar to the logic used in extensions/MozProjectReview/web/js/moz_project_review.js
+
+ if ($params->{new_or_change} eq 'New') {
+ $do_legal = 1;
+ }
+
+ if ($params->{mozilla_data} eq 'Yes') {
+ $do_legal = 1;
+ $do_privacy_policy = 1;
+ $do_privacy_tech = 1;
+ $do_sec_review = 1;
+ }
+
+ if ($params->{mozilla_data} eq 'Yes'
+ && $params->{data_safety_user_data} eq 'Yes')
+ {
+ $do_data_safety = 1;
+ }
+
+ if ($params->{separate_party} eq 'Yes') {
+ if ($params->{relationship_type} ne 'Hardware Purchase') {
+ $do_legal = 1;
+ }
+
+ if ($params->{relationship_type} eq 'Hardware Purchase') {
+ $do_finance = 1;
+ }
+
+ if ($params->{data_access} eq 'Yes') {
+ $do_privacy_policy = 1;
+ $do_legal = 1;
+ $do_sec_review = 1;
+ }
+
+ if ($params->{data_access} eq 'Yes'
+ && $params->{'privacy_policy_vendor_user_data'} eq 'Yes')
+ {
+ $do_privacy_vendor = 1;
+ }
+
+ if ($params->{vendor_cost} eq '> $25,000'
+ || ($params->{vendor_cost} eq '<= $25,000'
+ && $params->{po_needed} eq 'Yes'))
+ {
+ $do_finance = 1;
+ }
+ }
+
+ my ($sec_review_bug, $legal_bug, $finance_bug, $privacy_vendor_bug,
+ $data_safety_bug, $privacy_tech_bug, $privacy_policy_bug, $error,
+ @dep_bug_comment, @dep_bug_errors);
+
+ if ($do_sec_review) {
+ my $bug_data = {
+ short_desc => 'Security Review: ' . $bug->short_desc,
+ product => 'mozilla.org',
+ component => 'Security Assurance: Review Request',
+ bug_severity => 'normal',
+ groups => [ 'mozilla-corporation-confidential' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'other',
+ blocked => $bug->bug_id,
+ };
+ my $new_bug = _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'sec-review', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ # For sec-review bugs, we need to set the sec-review?
+ # flag as well so we do that now.
+ if ($new_bug) {
+ my $flagtypes = Bugzilla::FlagType::match({ product_id => $new_bug->product_obj->id,
+ component_id => $new_bug->component_obj->id,
+ name => 'sec-review' });
+ if (scalar @$flagtypes) {
+ my $sec_review_flag = $flagtypes->[0];
+ my $new_flags = [{
+ type_id => $sec_review_flag->id,
+ status => '?'
+ }];
+ $new_bug->set_flags([], $new_flags);
+ $new_bug->update();
+ }
+ }
+ }
+
+ if ($do_legal) {
+ my $component = 'General';
+ if ($params->{new_or_change} eq 'Existing') {
+ $component = $params->{mozilla_project};
+ }
+
+ if ($params->{separate_party} eq 'Yes'
+ && $params->{relationship_type})
+ {
+ $component = ($params->{relationship_type} eq 'Other'
+ || $params->{relationship_type} eq 'Hardware Purchase')
+ ? 'General'
+ : $params->{relationship_type};
+ }
+
+ my $legal_summary = "Legal Review: ";
+ $legal_summary .= $params->{legal_other_party} . " - " if $params->{legal_other_party};
+ $legal_summary .= $bug->short_desc;
+
+ my $bug_data = {
+ short_desc => $legal_summary,
+ product => 'Legal',
+ component => $component,
+ bug_severity => 'normal',
+ priority => '--',
+ groups => [ 'legal' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'unspecified',
+ blocked => $bug->bug_id,
+ cc => $params->{'legal_cc'},
+ };
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'legal', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ if ($do_finance) {
+ my $bug_data = {
+ short_desc => 'Finance Review: ' . $bug->short_desc,
+ product => 'Finance',
+ component => 'Purchase Request Form',
+ bug_severity => 'normal',
+ priority => '--',
+ groups => [ 'finance' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'unspecified',
+ blocked => $bug->bug_id,
+ };
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'finance', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ if ($do_data_safety) {
+ my $bug_data = {
+ short_desc => 'Data Safety Review: ' . $bug->short_desc,
+ product => 'Data Safety',
+ component => 'General',
+ bug_severity => 'normal',
+ priority => '--',
+ groups => [ 'mozilla-corporation-confidential' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'unspecified',
+ blocked => $bug->bug_id,
+ };
+
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'data-safety', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ if ($do_privacy_tech) {
+ my $bug_data = {
+ short_desc => 'Privacy-Technical Review: ' . $bug->short_desc,
+ product => 'mozilla.org',
+ component => 'Security Assurance: Review Request',
+ bug_severity => 'normal',
+ priority => '--',
+ keywords => 'privacy-review-needed',
+ groups => [ 'mozilla-corporation-confidential' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'other',
+ blocked => $bug->bug_id,
+ };
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'privacy-tech', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ if ($do_privacy_policy) {
+ my $bug_data = {
+ short_desc => 'Privacy-Policy Review: ' . $bug->short_desc,
+ product => 'Privacy',
+ component => 'Product Review',
+ bug_severity => 'normal',
+ priority => '--',
+ groups => [ 'mozilla-corporation-confidential' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'unspecified',
+ blocked => $bug->bug_id,
+ };
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'privacy-policy', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ if ($do_privacy_vendor) {
+ my $bug_data = {
+ short_desc => 'Privacy / Vendor Review: ' . $bug->short_desc,
+ product => 'Privacy',
+ component => 'Vendor Review',
+ bug_severity => 'normal',
+ priority => '--',
+ groups => [ 'mozilla-corporation-confidential' ],
+ op_sys => 'All',
+ rep_platform => 'All',
+ version => 'unspecified',
+ blocked => $bug->bug_id,
+ };
+ _file_child_bug({ parent_bug => $bug, template_vars => $vars,
+ template_suffix => 'privacy-vendor', bug_data => $bug_data,
+ dep_comment => \@dep_bug_comment, dep_errors => \@dep_bug_errors });
+ }
+
+ Bugzilla->error_mode($error_mode_cache);
+
+ if (scalar @dep_bug_errors) {
+ warn "[Bug " . $bug->id . "] Failed to create additional moz-project-review bugs:\n" .
+ join("\n", @dep_bug_errors);
+ $vars->{message} = 'moz_project_review_creation_failed';
+ }
+
+ if (scalar @dep_bug_comment) {
+ my $comment = join("\n", @dep_bug_comment);
+ if (scalar @dep_bug_errors) {
+ $comment .= "\n\nSome erors occurred creating dependent bugs and have been recorded";
+ }
+ $bug->add_comment($comment);
+ $bug->update();
+ }
+}
+
+sub _file_child_bug {
+ my ($params) = @_;
+ my ($parent_bug, $template_vars, $template_suffix, $bug_data, $dep_comment, $dep_errors)
+ = @$params{qw(parent_bug template_vars template_suffix bug_data dep_comment dep_errors)};
+ my $template = Bugzilla->template;
+ my $new_bug;
+ eval {
+ my $comment;
+ my $full_template = "bug/create/comment-moz-project-review-$template_suffix.txt.tmpl";
+ $template->process($full_template, $template_vars, \$comment)
+ || ThrowTemplateError($template->error());
+ $bug_data->{comment} = $comment;
+ if ($new_bug = Bugzilla::Bug->create($bug_data)) {
+ $parent_bug->set_all({ dependson => { add => [ $new_bug->bug_id ] }});
+ Bugzilla::BugMail::Send($new_bug->id, { changer => Bugzilla->user });
+ }
+ };
+ if ($@ || !$new_bug) {
+ push(@$dep_comment, "Error creating $template_suffix review bug");
+ push(@$dep_errors, "$template_suffix : $@") if $@;
+ }
+ else {
+ push(@$dep_comment, "Bug " . $new_bug->id . " - " . $new_bug->short_desc);
+ }
+ return $new_bug;
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-data-safety.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-data-safety.txt.tmpl
new file mode 100644
index 000000000..5a6ffbbbd
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-data-safety.txt.tmpl
@@ -0,0 +1,40 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Data Safety Questions:
+
+User Data: [% cgi.param('data_safety_user_data') %]
+How many involved?: [% cgi.param('data_safety_user_count') %]
+How many users do you anticipate to be involved?: [% cgi.param('data_safety_user_count_anticipated') %]
+Type of Data:
+[%+ cgi.param('data_safety_data_type') %]
+Data Reason:
+[%+ cgi.param('data_safety_data_reason') %]
+Community Benefit:
+[%+ cgi.param('data_safety_community_benefit') %]
+Data Collection:
+[%+ cgi.param('data_safety_community_collection') %]
+Data Retention: [% cgi.param('data_safety_retention') %]
+Data Retention Length: [% cgi.param('data_safety_retention_length') %]
+Separate Party: [% cgi.param('data_safety_separate_party') %]
+Separate Party Data Type:
+[%+ cgi.param('data_safety_separate_party_data') %]
+Separate Party Data Communication:
+[%+ cgi.param('data_safety_separate_party_data_communication') %]
+Who are the separate parties?:
+[%+ cgi.param('data_safety_separate_party_who') %]
+Community Visibility and Input: [% cgi.param('data_safety_community_visibility') %]
+Communication Channels:
+[%+ cgi.param('data_safety_communication_channels') %]
+Public Communication Plan:
+[%+ cgi.param('data_safety_communication_plan') %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-finance.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-finance.txt.tmpl
new file mode 100644
index 000000000..99691c287
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-finance.txt.tmpl
@@ -0,0 +1,31 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Finance Questions:
+
+Vendor: [% cgi.param('finance_purchase_vendor') %]
+Is this line item in budget?: [% cgi.param('finance_purchase_inbudget') %]
+[% IF cgi.param('finance_purchase_inbudget') == 'No' %]
+Not In Budget Why:
+[%+ cgi.param('finance_purchase_notinbudget_why') %]
+[% END %]
+What is the purchase for?:
+[%+ cgi.param('finance_purchase_what') %]
+Why is the purchase needed?:
+[%+ cgi.param('finance_purchase_why') %]
+What is the risk if not purchased?:
+[%+ cgi.param('finance_purchase_risk') %]
+What is the alternative?:
+[%+ cgi.param('finance_purchase_alternative') %]
+What is the urgency?: [% cgi.param('finance_purchase_urgency') %]
+Total Cost: [% cgi.param('finance_purchase_cost') %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-legal.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-legal.txt.tmpl
new file mode 100644
index 000000000..802caeee9
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-legal.txt.tmpl
@@ -0,0 +1,50 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Legal Questions:
+
+Priority: [% cgi.param('legal_priority') %]
+Other Party: [% cgi.param('legal_other_party') %]
+What help do you need from Legal?:
+[%+ cgi.param('legal_help_from_legal') %]
+[% IF cgi.param('legal_vendor_services_where') %]
+Vendor Services from Where:
+[% IF cgi.param('legal_vendor_services_where') == 'A single country' %]
+[%- cgi.param('legal_vendor_single_country') %]
+[% ELSE %]
+[%- cgi.param('legal_vendor_services_where') %]
+[% END %]
+[% END %]
+[% IF cgi.param('separate_party') == 'Yes' && cgi.param('relationship_type') == 'Vendor/Services' %]
+SOW Details:
+Legal Vendor Name: [% cgi.param('legal_sow_vendor_name') %]
+Vendor Address:
+[%+ cgi.param('legal_sow_vendor_address') %]
+Vendor Email for Notices: [% cgi.param('legal_sow_vendor_email') %]
+Mozilla Contact: [% cgi.param('legal_sow_vendor_mozcontact') %]
+Vendor Contact and Email Address: [% cgi.param('legal_sow_vendor_contact') %]
+Description of Services:
+[%+ cgi.param('legal_sow_vendor_services') %]
+Description of Deliverables:
+[%+ cgi.param('legal_sow_vendor_deliverables') %]
+Start Date: [% cgi.param('legal_sow_start_date') %]
+End Date: [% cgi.param('legal_sow_end_date') %]
+Rate of Pay: [% cgi.param('legal_sow_vendor_payment') %]
+Basis for Payment: [% cgi.param('legal_sow_vendor_payment_basis') %]
+Average/Maximum Hours: [% cgi.param('legal_sow_vendor_hours') %]
+Payment Schedule: [% cgi.param('legal_sow_vendor_payment_schedule') %]
+Total Not to Exceed Amount: [% cgi.param('legal_sow_vendor_total_max') %]
+Special Terms:
+[%+ cgi.param('legal_sow_vendor_special_terms') %]
+Product Line: [% cgi.param('legal_sow_vendor_product_line') %]
+[% END %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-policy.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-policy.txt.tmpl
new file mode 100644
index 000000000..816834c40
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-policy.txt.tmpl
@@ -0,0 +1,18 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Privacy Policy: [% cgi.param('privacy_policy_project') %]
+Privacy Policy Link: [% cgi.param('privacy_policy_project_link') %]
+User Data: [% cgi.param('privacy_policy_user_data') %]
+Data Safety [% terms.Bug %] ID: [% cgi.param('privacy_policy_user_data_bug') %]
+Legal [% terms.Bug %] ID: [% cgi.param('privacy_policy_legal_bug') %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-tech.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-tech.txt.tmpl
new file mode 100644
index 000000000..7b72cf1bc
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-tech.txt.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-vendor.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-vendor.txt.tmpl
new file mode 100644
index 000000000..eaf9f12e3
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-privacy-vendor.txt.tmpl
@@ -0,0 +1,16 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Privacy Policy: [% cgi.param('privacy_policy_vendor_user_data') %]
+Vendor's Privacy Policy: [% cgi.param('privacy_policy_vendor_link') %]
+Privacy Questionnaire: [% cgi.param('privacy_policy_vendor_questionnaire') %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-sec-review.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-sec-review.txt.tmpl
new file mode 100644
index 000000000..029f6df48
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review-sec-review.txt.tmpl
@@ -0,0 +1,20 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% PROCESS "bug/create/comment-moz-project-review.txt.tmpl" %]
+
+Security Review Questions:
+
+Affects Products: [% cgi.param('sec_affects_products') %]
+Review Due Date: [% cgi.param('sec_review_date') %]
+Review Invitees: [% cgi.param('sec_review_invitees') %]
+Extra Information:
+[%+ cgi.param('sec_review_extra') %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review.txt.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review.txt.tmpl
new file mode 100644
index 000000000..6a88aadd8
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/comment-moz-project-review.txt.tmpl
@@ -0,0 +1,36 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Initial Questions:
+
+Project/Feature Name: [% cgi.param('short_desc') %]
+Tracking [% terms.Bug %] ID:[% cgi.param('tracking_id') %]
+Description:
+[%+ cgi.param('description') %]
+Additional Information:
+[%+ cgi.param('additional') %]
+Urgency: [% cgi.param('urgency') %]
+Key Initiative: [% cgi.param('key_initiative') == 'Other'
+ ? cgi.param('key_initiative_other')
+ : cgi.param('key_initiative') %]
+Release Date: [% cgi.param('release_date') %]
+Project Status: [% cgi.param('project_status') %]
+Mozilla Data: [% cgi.param('mozilla_data') %]
+New or Change: [% cgi.param('new_or_change') %]
+Mozilla Project: [% cgi.param('mozilla_project') %]
+Mozilla Related: [% cgi.param('mozilla_related') %]
+Separate Party: [% cgi.param('separate_party') %]
+[% IF cgi.param('separate_party') == 'Yes' %]
+Type of Relationship: [% cgi.param('relationship_type') %]
+Data Access: [% cgi.param('data_access') %]
+Privacy Policy: [% cgi.param('privacy_policy') %]
+Vendor Cost: [% cgi.param('vendor_cost') %]
+[% END %]
diff --git a/extensions/MozProjectReview/template/en/default/bug/create/create-moz-project-review.html.tmpl b/extensions/MozProjectReview/template/en/default/bug/create/create-moz-project-review.html.tmpl
new file mode 100644
index 000000000..18d7ae786
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/bug/create/create-moz-project-review.html.tmpl
@@ -0,0 +1,915 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Project Review"
+ style_urls = [ 'extensions/MozProjectReview/web/style/moz_project_review.css' ]
+ javascript_urls = [ 'js/field.js', 'js/util.js',
+ 'extensions/MozProjectReview/web/js/moz_project_review.js' ]
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+<p>
+ <strong>Please use this form for submitting a Mozilla Project Review</strong>
+ If you have a [% terms.bug %] to file, go <a href="enter_bug.cgi">here</a>.
+</p>
+
+<p>
+ (<span class="required_star">*</span> =
+ <span class="required_explanation">Required Field</span>)
+</p>
+
+<form method="post" action="post_bug.cgi" id="incidentForm" enctype="multipart/form-data"
+ onSubmit="return MPR.validateAndSubmit();">
+ <input type="hidden" id="product" name="product" value="mozilla.org">
+ <input type="hidden" id="component" name="component" value="Project Review">
+ <input type="hidden" id="rep_platform" name="rep_platform" value="All">
+ <input type="hidden" id="groups" name="groups" value="mozilla-corporation-confidential">
+ <input type="hidden" id="op_sys" name="op_sys" value="All">
+ <input type="hidden" id="priority" name="priority" value="--">
+ <input type="hidden" id="version" name="version" value="other">
+ <input type="hidden" id="format" name="format" value="moz-project-review">
+ <input type="hidden" id="bug_severity" name="bug_severity" value="normal">
+ <input type="hidden" id="token" name="token" value="[% token FILTER html %]">
+
+ <div id="initial_questions">
+ <div class="header">Initial Questions</div>
+
+ <div id="project_feature_summary_row" class="field_row">
+ <span class="field_label required">Project/Feature Name:</span>
+ <span class="field_data">
+ <div class="field_description">Be brief yet descriptive as possible. Include name of product,
+ feature, or name of vendor involved as well if appropriate.</div>
+ <input type="text" name="short_desc" id="short_desc" size="60" maxsize="255">
+ </span>
+ </div>
+
+ <div id="tracking_id_row" class="field_row">
+ <span class="field_label">Tracking [% terms.Bug %] ID:</span>
+ <span class="field_data">
+ <div class="field_description">Master tracking [% terms.bug %] number (if it exists)?</div>
+ <input type="text" name="tracking_id" id="tracking_id" size="60">
+ </span>
+ </div>
+
+ <div id="contacts_row" class="field_row">
+ <span class="field_label required">Points of Contact:</span>
+ <span class="field_data">
+ <div class="field_description">Who are the points of contact for this review?</div>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => ""
+ size => 60
+ classes => ["bz_userfield"]
+ multiple => 5
+ %]
+ </span>
+ </div>
+
+ <div id="description_row" class="field_row">
+ <span class="field_label required">Description:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide a short description of the feature / application / project /
+ business relationship (e.g. problem solved, use cases, etc.)</div>
+ <textarea name="description" id="description" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="additional_row" class="field_row">
+ <span class="field_label">Additional Information:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide links to additional information (e.g. feature page, wiki)
+ if available and not yet included in feature description.)</div>
+ <textarea name="additional" id="additional" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="urgency_row" class="field_row">
+ <span class="field_label required">Urgency:</span>
+ <span class="field_data">
+ <div class="field_description">What is the urgency of this project?</div>
+ <select id="urgency" name="urgency">
+ <option value="">Select One</option>
+ <option value="no rush">no rush</option>
+ <option value="2-4 weeks">2-4 weeks</option>
+ <option value="a week">a week</option>
+ <option value="2 days">2 days</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="key_initiative_row" class="field_row">
+ <span class="field_label required">Key Initiative:</span>
+ <span class="field_data">
+ <div class="field_description">Which key initiative does this support?</div>
+ <select name="key_initiative" id="key_initiative">
+ <option value="">Select One</option>
+ <option value="Firefox Desktop">Firefox Desktop</option>
+ <option value="Firefox Mobile">Firefox Mobile</option>
+ <option value="Firefox OS">Firefox OS</option>
+ <option value="Firefox Platform">Firefox Platform</option>
+ <option value="Marketplace / Apps">Marketplace / Apps</option>
+ <option value="Services: Persona">Services: Persona</option>
+ <option value="Services: WebRTC">Services: WebRTC</option>
+ <option value="Services: UP">Services: UP</option>
+ <option value="Services: Social API">Services: Social API</option>
+ <option value="Labs / Research / H3">Labs / Research / H3</option>
+ <option value="Product Support">Product Support</option>
+ <option value="Corp Support">Corp Support</option>
+ <option value="Other">Other</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="key_initiative_other_row" class="field_row bz_default_hidden">
+ <span class="field_label">&nbsp;</span>
+ <span class="field_data">
+ <input type="text" name="key_initiative_other" id="key_initiative_other" size="60">
+ </span>
+ </div>
+
+ <div id="release_date_row" class="field_row">
+ <span class="field_label">Release Date:</span>
+ <span class="field_data">
+ <div class="field_description">What is your overall key release / launch date / go live date?</div>
+ <input name="release_date" size="20" id="release_date" value=""
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_release_date"
+ onclick="showCalendar('release_date')">
+ <span>Calendar</span>
+ </button>
+ <div id="con_calendar_release_date"></div>
+ <script type="text/javascript">
+ createCalendar('release_date')
+ </script>
+ </span>
+ </div>
+
+ <div id="project_status_row" class="field_row">
+ <span class="field_label required">Project Status:</span>
+ <span class="field_data">
+ <div class="field_description">What is the current state of your project?</div>
+ <select name="project_status" id="project_status">
+ <option value="">Select One</option>
+ <option value="future">Future project under discussion</option>
+ <option value="active">Active planning</option>
+ <option value="development">Development</option>
+ <option value="ready">Ready to launch/commit</option>
+ <option value="launched">Already launched/committed</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="mozilla_data_row" class="field_row">
+ <span class="field_label required">Mozilla Data:</span>
+ <span class="field_data">
+ <div class="field_description">Does this product/service/project access, interact with, or store Mozilla
+ (customer, contributor, user, employee) data? Example of such data includes
+ email addresses, first and last name, addresses, phone numbers, credit card data.)</div>
+ <select name="mozilla_data" id="mozilla_data">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="new_or_change_row" class="field_row">
+ <span class="field_label required">New or Change:</span>
+ <span class="field_data">
+ <div class="field_description">Is this a NEW product, service, project, feature, or functionality,
+ a change to an EXISTING one, or neither?</div>
+ <select name="new_or_change" id="new_or_change">
+ <option value="">Select One</option>
+ <option value="New">New</option>
+ <option value="Existing">Existing</option>
+ <option value="Neither">Neither</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="mozilla_project_row" class="field_row bz_default_hidden">
+ <span class="field_label">Mozilla Project:</span>
+ <span class="field_data">
+ <div class="field_description">What product/service/project does this pertain to?</div>
+ <select name="mozilla_project" id="mozilla_project">
+ <option value="General">None</option>
+ <option value="FirefoxOS">FirefoxOS</option>
+ <option value="Marketplace">Marketplace</option>
+ <option value="Persona">Persona</option>
+ <option value="Marketing Initiative">Marketing Initiative</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="mozilla_related_row" class="field_row">
+ <span class="field_label">Mozilla Related:</span>
+ <span class="field_data">
+ <div class="field_description">What Mozilla products/services/projects does this product/service/project
+ integrate with or relate to?</div>
+ <input type="text" name="mozilla_related" id="mozilla_related" size="60">
+ </span>
+ </div>
+
+ <div id="separate_party_row" class="field_row">
+ <span class="field_label required">Separate Party:</span>
+ <span class="field_data">
+ <div class="field_description">Hardware Purchases,
+ Vendor agreements, NDAs, Contracts etc</div>
+ <select name="separate_party" id="separate_party">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="initial_separate_party_questions" class="bz_default_hidden">
+ <div id="relation_type_row" class="field_row">
+ <span class="field_label required">Type of Relationship:</span>
+ <span class="field_data">
+ <div class="field_description">What type of relationship?</div>
+ <select name="relationship_type" id="relationship_type">
+ <option value="">Select One</option>
+ <option value="Hardware Purchase">Hardware Purchase</option>
+ <option value="Vendor/Services">Vendor/Services</option>
+ <option value="Distribution/Bundling">Distribution/Bundling</option>
+ <option value="Search">Search</option>
+ <option value="NDA">NDA</option>
+ <option value="Other">Other</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="data_access_row" class="field_row">
+ <span class="field_label required">Data Access:</span>
+ <span class="field_data">
+ <div class="field_description">Will the other party have access to Mozilla (customer, contributor, user,
+ employee) data? (If this is for an NDA, choose no)</div>
+ <select name="data_access" id="data_access">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="privacy_policy_row" class="field_row">
+ <span class="field_label">Privacy Policy:</span>
+ <span class="field_data">
+ <div class="field_description">What is the url for their privacy policy?</div>
+ <input type="text" name="privacy_policy" id="privacy_policy" size="60">
+ </span>
+ </div>
+
+ <div id="vendor_cost_row" class="field_row">
+ <span class="field_label required">Vendor Cost:</span>
+ <span class="field_data">
+ <div class="field_description">What is the anticipated cost of the vendor relationship?
+ (Entire Contract Cost, not monthly cost)</div>
+ <select name="vendor_cost" id="vendor_cost">
+ <option value="">Select One</option>
+ <option value="N/A">N/A</option>
+ <option value="&lt;= $25,000">&lt;= $25,000</option>
+ <option value="&gt; $25,000">&gt; $25,000</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="po_needed_row" class="field_row bz_default_hidden">
+ <span class="field_label required">PO Needed?:</span>
+ <span class="field_data">
+ <select name="po_needed" id="po_needed">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <div id="sec_review_questions" class="bz_default_hidden">
+ <div class="header">Security Review</div>
+
+ <div id="sec_review_affects_products_row">
+ <span class="field_label">Affects Products:</span>
+ <span class="field_data">
+ <div class="field_description">Does this feature or code change affect Firefox, Thunderbird or any
+ product or service the Mozilla ships to end users?</div>
+ <select name="sec_affects_products" id="sec_affects_products">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="sec_review_date_row" class="field_row">
+ <span class="field_label">Review Due Date:</span>
+ <span class="field_data">
+ <div class="field_description">When would you like the review to be completed?
+ (<a href="https://mail.mozilla.com/home/ckoenig@mozilla.com/Security%20Review.html"
+ target="_blank">more info</a>)</div>
+ <input name="sec_review_date" size="20" id="sec_review_date" value=""
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_sec_review_date"
+ onclick="showCalendar('sec_review_date')">
+ <span>Calendar</span>
+ </button>
+ <div id="con_calendar_sec_review_date"></div>
+ <script type="text/javascript">
+ createCalendar('sec_review_date')
+ </script>
+ </span>
+ </div>
+
+ <div id="sec_review_invitees_row" class="field_row">
+ <span class="field_label">Review Invitees:</span>
+ <span class="field_data">
+ <div class="field_description">Whom should be invited to the review?</div>
+ <input type="text" name="sec_review_invitees" id="sec_review_invitees" size="60">
+ </span>
+ </div>
+
+ <div id="sec_review_extra_row" class="field_row">
+ <span class="field_label">Extra Information:</span>
+ <span class="field_data">
+ <div class="field_description">If you feel something is missing here or you would like to provide other
+ kind of feedback, feel free to do so here?</div>
+ <textarea name="sec_review_extra" id="sec_review_extra" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+ </div>
+
+ <div id="privacy_policy_project_questions" class="bz_default_hidden">
+ <div class="header">Privacy (Policy/Project)</div>
+
+ <div id="privacy_policy_project_row" class="field_row">
+ <span class="field_label">Privacy Policy:</span>
+ <span class="field_data">
+ <div class="field_description">Do you currently have a privacy policy for your project / site / product?</div>
+ <select name="privacy_policy_project" id="privacy_policy_project">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="privacy_policy_project_link_row" class="field_row bz_default_hidden">
+ <span class="field_label">Privacy Policy Link:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide link to policy</div>
+ <input type="text" name="privacy_policy_project_link" id="privacy_policy_project_link" size="60">
+ </span>
+ </div>
+
+ <div id="privacy_policy_project_user_data_row" class="field_row">
+ <span class="field_label">User Data:</span>
+ <span class="field_data">
+ <div class="field_description">Does your product/service/project collect, use or maintain any user data?</div>
+ <select name="privacy_policy_user_data" id="privacy_policy_user_data">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="privacy_policy_project_user_data_bug_row" class="bz_default_hidden">
+ <span class="field_label">Data Safety [% terms.Bug %] ID:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide link to Data Safety [% terms.bug %]</div>
+ <input type="text" name="privacy_policy_user_data_bug" id="privacy_policy_user_data_bug" size="60">
+ </span>
+ </div>
+
+ <div id="privacy_policy_project_legal_bug_row" class="field_row">
+ <span class="field_label">Legal [% terms.Bug %]:</span>
+ <span class="field_data">
+ <div class="field_description">For reference, please provide link to related Legal [% terms.bug %] or enter
+ "not filed" if a legal [% terms.bug %] has not yet been filed.</div>
+ <input type="text" name="privacy_policy_legal_bug" id="privacy_policy_legal_bug" size="60">
+ </span>
+ </div>
+ </div>
+
+ <div id="privacy_policy_vendor_questions" class="bz_default_hidden">
+ <div class="header">Privacy (Policy/Vendor)</div>
+
+ <div id="privacy_policy_vendor_user_data_row" class="field_row">
+ <span class="field_label">Privacy Policy:</span>
+ <span class="field_data">
+ <div class="field_description">Will the vendor have access to Mozilla (customer, contributor, user, employee) data?</div>
+ <select name="privacy_policy_vendor_user_data" id="privacy_policy_vendor_user_data">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="privacy_policy_vendor_extra" class="bz_default_hidden">
+ <div id="privacy_policy_vendor_link_row" class="field_row">
+ <span class="field_label">Vendor's Privacy Policy:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide link to vendor's privacy policy</div>
+ <input type="text" name="privacy_policy_vendor_link" id="privacy_policy_vendor_link" size="60">
+ </span>
+ </div>
+
+ <div id="privacy_policy_vendor_questionnaire_row" class="field_row">
+ <span class="field_label">Privacy Questionnaire:</span>
+ <span class="field_data">
+ <div class="field_description">Has vendor completed Mozilla Vendor Privacy Questionnaire?</div>
+ <select name="privacy_policy_vendor_questionnaire" id="privacy_policy_vendor_questionnaire">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <div id="legal_questions" class="bz_default_hidden">
+ <div class="header">Legal</div>
+
+ <div id="legal_priority_row" class="field_row">
+ <span class="field_label required">Priority:</span>
+ <span class="field_data">
+ <div class="field_description">Priority to your team</div>
+ <select name="legal_priority" id="legal_priority">
+ <option value="">Select One</option>
+ <option value="high">High</option>
+ <option value="medium">Medium</option>
+ <option value="low">Low</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="legal_cc_row" class="field_row">
+ <span class="field_label">Cc:</span>
+ <span class="field_data">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "legal_cc"
+ name => "legal_cc"
+ value => ""
+ size => 60
+ classes => ["bz_userfield"]
+ multiple => 5
+ %]
+ </span>
+ </div>
+
+ <div id="legal_other_party_row" class="field_row">
+ <span class="field_label">Other Party:</span>
+ <span class="field_data">
+ <div class="field_description">Name of other party involved</div>
+ <input type="text" name="legal_other_party" id="legal_other_party" size="60">
+ </span>
+ </div>
+
+ <div id="legal_help_from_legal_row" class="field_row">
+ <span class="field_label required">What help do you<br>need from Legal?</span>
+ <span class="field_data">
+ <div class="field_description">
+ Please explain specifically what help you need from Legal. If none, put "No Legal help needed."</div>
+ <textarea name="legal_help_from_legal" id="legal_help_from_legal" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="legal_sow_questions" class="bz_default_hidden">
+ <div class=field_row">
+ <span class="field_label">SOW Details:</span>
+ <span class="field_data">
+ Please provide the following information for the SOW
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_name_row" class="field_row">
+ <span class="field_label required">Legal Vendor Name:</span>
+ <span class="field_data">
+ <input type="text" name="legal_sow_vendor_name" id="legal_sow_vendor_name" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_address_row" class="field_row">
+ <span class="field_label required">Vendor Address:</span>
+ <span class="field_data">
+ <textarea name="legal_sow_vendor_address" id="legal_sow_vendor_address" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_email_row" class="field_row">
+ <span class="field_label required">Vendor Email for Notices:</span>
+ <span class="field_data">
+ <input type="text" name="legal_sow_vendor_email" id="legal_sow_vendor_email" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_mozcontact_row" class="field_row">
+ <span class="field_label required">Main Mozilla Contact:</span>
+ <span class="field_data">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "legal_sow_vendor_mozcontact"
+ name => "legal_sow_vendor_mozcontact"
+ value => ""
+ size => 60
+ classes => ["bz_userfield"]
+ multiple => 5
+ %]
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_contact_row" class="field_row">
+ <span class="field_label required">Main Vendor Contact and Email:</span>
+ <span class="field_data">
+ <input type="text" name="legal_sow_vendor_contact" id="legal_sow_vendor_contact" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_services_row" class="field_row">
+ <span class="field_label required">Vendor Services to be Provided:</span>
+ <span class="field_data">
+ <textarea name="legal_sow_vendor_services" id="legal_sow_vendor_services" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_deliverables_row" class="field_row">
+ <span class="field_label required">Description of Deliverables:</span>
+ <span class="field_data">
+ <textarea name="legal_sow_vendor_deliverables" id="legal_sow_vendor_deliverables" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="legal_sow_start_date_row" class="field_row">
+ <span class="field_label required">Start Date:</span>
+ <span class="field_data">
+ <input name="legal_sow_start_date" size="20" id="legal_sow_start_date" value=""
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_legal_sow_start_date"
+ onclick="showCalendar('legal_sow_start_date')">
+ <span>Calendar</span>
+ </button>
+ <div id="con_calendar_legal_sow_start_date"></div>
+ <script type="text/javascript">
+ createCalendar('legal_sow_start_date')
+ </script>
+ </span>
+ </div>
+
+ <div id="legal_sow_end_date_row" class="field_row">
+ <span class="field_label required">End Date:</span>
+ <span class="field_data">
+ <input name="legal_sow_end_date" size="20" id="legal_sow_end_date" value=""
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_legal_sow_end_date"
+ onclick="showCalendar('legal_sow_end_date')">
+ <span>Calendar</span>
+ </button>
+ <div id="con_calendar_legal_sow_end_date"></div>
+ <script type="text/javascript">
+ createCalendar('legal_sow_end_date')
+ </script>
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_payment_row" class="field_row">
+ <span class="field_label required">Rate of Pay:</span>
+ <span class="field_data">
+ <div class="field_description">Include currency</div>
+ <input type="text" name="legal_sow_vendor_payment" id="legal_sow_vendor_payment" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_payment_basis_row" class="field_row">
+ <span class="field_label required">Basis for Payment:</span>
+ <span class="field_data">
+ <div class="field_description">hourly, flat fee, per deliverable, etc.</div>
+ <input type="text" name="legal_sow_vendor_payment_basis" id="legal_sow_vendor_payment_basis" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_hours_row" class="field_row">
+ <span class="field_label">Average/Max Hours:</span>
+ <span class="field_data">
+ <div class="field_description">If hourly, either average or maximum hours per week/month</div>
+ <input type="text" name="legal_sow_vendor_hours" id="legal_sow_vendor_hours" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_payment_schedule_row" class="field_row">
+ <span class="field_label required">Payment Schedule:</span>
+ <span class="field_data">
+ <div class="field_description">"When will we make payments? E.g. every 30 days; half due up front,
+ half on completion; following acceptance of each deliverable, etc.</div>
+ <input type="text" name="legal_sow_vendor_payment_schedule" id="legal_sow_vendor_payment_schedule" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_total_max_row" class="field_row">
+ <span class="field_label required">Total Not to Exceed Amount:</span>
+ <span class="field_data">
+ <input type="text" name="legal_sow_vendor_total_max" id="legal_sow_vendor_total_max" size="60">
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_special_terms_row" class="field_row">
+ <span class="field_label">Any Special Terms:</span>
+ <span class="field_data">
+ <textarea name="legal_sow_vendor_special_terms" id="legal_sow_vendor_special_terms" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="legal_sow_vendor_product_line_row" class="field_row">
+ <span class="field_label required">Product Line:</span>
+ <span class="field_data">
+ <select id="legal_sow_vendor_product_line" name="legal_sow_vendor_product_line">
+ <option value="">Select One</option>
+ <option value="Firefox OS">Firefox OS</option>
+ <option value="Firefox Desktop">Firefox Desktop</option>
+ <option value="Firefox Mobile">Firefox Mobile</option>
+ <option value="Firefox Platform">Firefox Platform</option>
+ <option value="Marketplace/Apps">Marketplace/Apps</option>
+ <option value="Lab/Research">Lab/Research</option>
+ <option value="Services">Services</option>
+ <option value="Product Support">Product Support</option>
+ <option value="Corp Support">Corp Support</option>
+ </select>
+ </span>
+ </div>
+ </div>
+
+ <div id="legal_vendor_services_where_row" class="field_row bz_default_hidden">
+ <span class="field_label required">Vendor Services Location:</span>
+ <span class="field_data">
+ <div class="field_description">Where will the services primarily be provided?</div>
+ <select name="legal_vendor_services_where" id="legal_vendor_services_where">
+ <option value="">Select One</option>
+ <option value="U.S.">U.S.</option>
+ <option value="Europe">Europe</option>
+ <option value="Canada">Canada</option>
+ <option value="Global">Global</option>
+ <option value="Another region of the world">Another region of the world</option>
+ <option value="A single country">A single country</option>
+ </select>
+ <br>
+ <input class="bz_default_hidden" type="text"
+ name="legal_vendor_single_country" id="legal_vendor_single_country" size="60">
+ </span>
+ </div>
+ </div>
+
+ <div id="finance_questions" class="bz_default_hidden">
+ <div class="header">Finance</div>
+
+ <div id="finance_purchase_vendor_row" class="field_row">
+ <span class="field_label required">Vendor:</span>
+ <span class="field_data">
+ <input type="text" name="finance_purchase_vendor" maxsize="255" size="60" id="finance_purchase_vendor">
+ </span>
+ </div>
+
+ <div id="finance_purchase_inbudget_row" class="field_row">
+ <span class="field_label required">Is this line item in budget?:</span>
+ <span class="field_data">
+ <select name="finance_purchase_inbudget" id="finance_purchase_inbudget">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="finance_purchase_notinbudget_why_row" class="field_row bz_default_hidden">
+ <span class="field_label required">Not In Budget Why:</span>
+ <span class="field_data">
+ <em>Please include additional description for this out of budget line item</em><br>
+ <textarea name="finance_purchase_notinbudget_why" id="finance_purchase_notinbudget_why" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="finance_purchase_what_row" class="field_row">
+ <span class="field_label required">What is the purchase for?:</span>
+ <span class="field_data">
+ <textarea name="finance_purchase_what" id="finance_purchase_what" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="finance_purchase_why_row" class="field_row">
+ <span class="field_label required">Why is the purchase needed?:</span>
+ <span class="field_data">
+ <textarea name="finance_purchase_why" id="finance_purchase_why" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="finance_purchase_risk_row" class="field_row">
+ <span class="field_label required">What is the risk<br>if not purchased?:</span>
+ <span class="field_data">
+ <textarea name="finance_purchase_risk" id="finance_purchase_risk" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="finance_purchase_alternative_row" class="field_row">
+ <span class="field_label required">What is the alternative?:</span>
+ <span class="field_data">
+ <textarea name="finance_purchase_alternative" id="finance_purchase_alternative" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="finance_purchase_urgency_row" class="field_row">
+ <span class="field_label required">When do the items need<br>to be ordered by?:</span>
+ <span class="field_data">
+ <select name="finance_purchase_urgency" id="finance_purchase_urgency">
+ <option value="within 24 hours">within 24 hours</option>
+ <option value="1 to 3 days">1 to 3 days</option>
+ <option value="a week">a week</option>
+ <option value="no rush" selected>no rush</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="finance_purchase_cost_row" class="field_row">
+ <span class="field_label required">Total Cost:</span>
+ <span class="field_data">
+ <input type="text" name="finance_purchase_cost" id="finance_purchase_cost" size="60">
+ </span>
+ </div>
+ </div>
+
+ <div id="data_safety_questions" class="bz_default_hidden">
+ <div class="header">Data Safety</div>
+
+ <div id="data_safety_user_data_row" class="field_row">
+ <span class="field_label">User Data:</span>
+ <span class="field_data">
+ <div class="field_description">Does your project collect data from users?</div>
+ <select name="data_safety_user_data" id="data_safety_user_data">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="data_safety_extra_questions" class="bz_default_hidden">
+ <div id="data_safety_user_count_row" class="field_row">
+ <span class="field_label">How many involved?:</span>
+ <span class="field_data">
+ <div class="field_description">How many users are currently involved?</div>
+ <input type="text" name="data_safety_user_count" id="data_safety_user_count" size="60">
+ </span>
+ </div>
+
+ <div id="data_safety_user_count_anticipated_row" class="field_row">
+ <span class="field_label">How many antcipated?:</span>
+ <span class="field_data">
+ <div class="field_description">How many users do you anticipate to be involved?</div>
+ <input type="text" name="data_safety_user_count_anticipated" id="data_safety_user_count_anticipated" size="60">
+ </span>
+ </div>
+
+ <div id="data_safety_data_type_row" class="field_row">
+ <span class="field_label">Type of Data:</span>
+ <span class="field_data">
+ <div class="field_description">Please provide examples of the types of user data you collect.</div>
+ <textarea name="data_safety_data_type" id="data_safety_data_type" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_data_reason_row" class="field_row">
+ <span class="field_label">Data Reason:</span>
+ <span class="field_data">
+ <div class="field_description">Why do you need to collect user data?</div>
+ <textarea name="data_safety_data_reason" id="data_safety_data_reason" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_community_benefit_row" class="field_row">
+ <span class="field_label">Community Benefit:</span>
+ <span class="field_data">
+ <div class="field_description">What community benefits are derived from the collection of user data for your project?</div>
+ <textarea name="data_safety_community_benefit" id="data_safety_community_benefit" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_community_collection_row" class="field_row">
+ <span class="field_label">Data Collection:</span>
+ <span class="field_data">
+ <div class="field_description">How is the data being collected? (e.g., forms on web site, provided directly by user,
+ observed data collection, etc.) (Consider that you may be collecting data unintentionally
+ such as automatic logging by web servers)</div>
+ <textarea name="data_safety_community_collection" id="data_safety_community_collection" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_retention_row" class="field_row">
+ <span class="field_label">Data Retention:</span>
+ <span class="field_data">
+ <div class="field_description">Will your project / team members need to retain user data?</div>
+ <select name="data_safety_retention" id="data_safety_retention">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="data_safety_retention_length_row" class="field_row bz_default_hidden">
+ <span class="field_label">Data Retention Length:</span>
+ <span class="field_data">
+ <div class="field_description">If the data is being retained, for how long?</div>
+ <input type="text" name="data_safety_retention_length" id="data_safety_retention_length" size="60"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_separate_party_row" class="field_row">
+ <span class="field_label">Separate Party:</span>
+ <span class="field_data">
+ <div class="field_description">Will any user data be shared or accessed by third party partners, customers or providers?</div>
+ <select name="data_safety_separate_party" id="data_safety_separate_party">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="data_safety_separate_party_extra" class="bz_default_hidden">
+ <div id="data_safety_separate_party_data_row" class="field_row">
+ <span class="field_label">Separate Party Data Type:</span>
+ <span class="field_data">
+ <div class="field_description">What is the data being shared or accessed?</div>
+ <textarea name="data_safety_separate_party_data" id="data_safety_community_separate_party_data" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_separate_party_data_communication_row" class="field_row">
+ <span class="field_label">Separate Party<br>Data Communication:</span>
+ <span class="field_data">
+ <div class="field_description">How would the data be communicated / transferred to the third parties?</div>
+ <textarea name="data_safety_separate_party_data_communication" id="data_safety_separate_party_data_communication" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_separate_party_who_row" class="field_row">
+ <span class="field_label">Who are the separate parties?:</span>
+ <span class="field_data">
+ <div class="field_description">Who are the third party vendors and in what countries are they based?</div>
+ <textarea name="data_safety_separate_party_who" id="data_safety_separate_party_who" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+ </div>
+
+ <div id="data_safety_community_visibility_row" class="field_row">
+ <span class="field_label">Community Visibility and Input:</span>
+ <span class="field_data">
+ <div class="field_description">Has your proposal been shared publicly, including requirements for Mozilla to collect and host user data?</div>
+ <select name="data_safety_community_visibility" id="data_safety_community_visibility">
+ <option value="">Select One</option>
+ <option value="Yes">Yes</option>
+ <option value="No">No</option>
+ </select>
+ </span>
+ </div>
+
+ <div id="data_safety_communication_channels_row" class="field_row bz_default_hidden">
+ <span class="field_label">Communication Channels:</span>
+ <span class="field_data">
+ <div class="field_description">What communication channels are you using and what kind of input have you received thus far?</div>
+ <textarea name="data_safety_communication_channels" id="data_safety_communication_channels" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+
+ <div id="data_safety_communication_plan_row" class="field_row bz_default_hidden">
+ <span class="field_label">Public Communication Plan:</span>
+ <span class="field_data">
+ <div class="field_description">Data Safety discussion needed. Provide your plan for publicly sharing your proposal.</div>
+ <textarea name="data_safety_communication_plan" id="data_safety_communication_plan" rows="10" cols="80"></textarea>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <input type="submit" id="commit" value="Submit Review">
+</form>
+
+<p>
+ Thanks for contacting us. You will be notified by email of any progress made in resolving your request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/MozProjectReview/template/en/default/hook/global/messages-messages.html.tmpl b/extensions/MozProjectReview/template/en/default/hook/global/messages-messages.html.tmpl
new file mode 100644
index 000000000..ac7c1f6c7
--- /dev/null
+++ b/extensions/MozProjectReview/template/en/default/hook/global/messages-messages.html.tmpl
@@ -0,0 +1,13 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF message_tag == "moz_project_review_creation_failed" %]
+ The parent [% terms.bug %] was created successfully, but creation of
+ the dependent [% terms.bugs %] failed. The error has been logged
+ and no further action is required at this time.
+[% END %]
diff --git a/extensions/MozProjectReview/web/js/moz_project_review.js b/extensions/MozProjectReview/web/js/moz_project_review.js
new file mode 100644
index 000000000..dca67f2ae
--- /dev/null
+++ b/extensions/MozProjectReview/web/js/moz_project_review.js
@@ -0,0 +1,307 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+var Dom = YAHOO.util.Dom;
+var Event = YAHOO.util.Event;
+
+var MPR = {
+ required_fields: {
+ "initial_questions": {
+ "short_desc": "Please enter a value for project or feature name in the initial questions section",
+ "cc": "Please enter a value for points of contact in the initial questions section",
+ "urgency": "Please enter a value for urgency in the initial questions section",
+ "key_initiative": "Please select a value for key initiative in the initial questions section",
+ "project_status": "Please select a value for project status in the initial questions section",
+ "mozilla_data": "Please select a value for mozilla data in the initial questions section",
+ "new_or_change": "Please select a value for new or change to existing project in the initial questions section",
+ "separate_party": "Please select a value for separate party in the initial questions section"
+ },
+ "finance_questions": {
+ "finance_purchase_vendor": "Please enter a value for vendor in the finance questions section",
+ "finance_purchase_what": "Please enter a value for what in the finance questions section",
+ "finance_purchase_why": "Please enter a value for why in the finance questions section",
+ "finance_purchase_risk": "Please enter a value for risk in the finance questions section",
+ "finance_purchase_alternative": "Please enter a value for alternative in the finance questions section",
+ "finance_purchase_inbudget": "Please enter a value for in budget in the finance questions section",
+ "finance_purchase_urgency": "Please select a value for urgency in the finance questions section",
+ "finance_purchase_cost": "Please enter a value for total cost in the finance questions section"
+ },
+ "legal_questions": {
+ "legal_priority": "Please select a priority for the legal questions section",
+ "legal_help_from_legal": "Please describe the help needed from the Legal department"
+ },
+ "legal_sow_questions": {
+ "legal_sow_vendor_name": "Please enter a value for SOW legal vendor name",
+ "legal_sow_vendor_address": "Please enter a value for SOW vendor address",
+ "legal_sow_vendor_email": "Please enter a value for SOW vendor email for notices",
+ "legal_sow_vendor_mozcontact": "Please enter a value for SOW Mozilla contact",
+ "legal_sow_vendor_contact": "Please enter a value for SOW vendor contact and email address",
+ "legal_sow_vendor_services": "Please enter a value for SOW vendor services description",
+ "legal_sow_vendor_deliverables": "Please enter a value for SOW vendor deliverables description",
+ "legal_sow_start_date": "Please enter a value for SOW vendor start date",
+ "legal_sow_end_date": "Please enter a value for SOW vendor end date",
+ "legal_sow_vendor_payment": "Please enter a value for SOW vendor payment amount",
+ "legal_sow_vendor_payment_basis": "Please enter a value for SOW vendor payment basis",
+ "legal_sow_vendor_payment_schedule": "Please enter a value for SOW vendor payment schedule",
+ "legal_sow_vendor_total_max": "Please enter a value for SOW vendor maximum total to be paid",
+ "legal_sow_vendor_product_line": "Please enter a value for SOW vendor product line"
+ }
+ },
+
+ select_inputs: [
+ 'urgency',
+ 'key_initiative',
+ 'project_status',
+ 'mozilla_data',
+ 'new_or_change',
+ 'mozilla_project',
+ 'separate_party',
+ 'relationship_type',
+ 'data_access',
+ 'vendor_cost',
+ 'po_needed',
+ 'sec_affects_products',
+ 'privacy_policy_project',
+ 'privacy_policy_user_data',
+ 'privacy_policy_vendor_user_data',
+ 'privacy_policy_vendor_questionnaire',
+ 'legal_priority',
+ 'legal_sow_vendor_product_line',
+ 'legal_vendor_services_where',
+ 'finance_purchase_inbudget',
+ 'finance_purchase_urgency',
+ 'data_safety_user_data',
+ 'data_safety_retention',
+ 'data_safety_separate_party',
+ 'data_safety_community_visibility'
+ ],
+
+ init: function () {
+ // Bind the updateSections function to each of the inputs desired
+ for (var i = 0, l = this.select_inputs.length; i < l; i++) {
+ Event.on(this.select_inputs[i], 'change', MPR.updateSections);
+ }
+ MPR.updateSections();
+ },
+
+ updateSections: function () {
+ // Sections that will be hidden/shown based on the input values
+ // Start out as all false except for initial questions which is always visible
+ var page_sections = {
+ initial_questions: true,
+ key_initiative_other_row: false,
+ initial_separate_party_questions: false,
+ finance_questions: false,
+ finance_purchase_notinbudget_why_row: false,
+ po_needed_row: false,
+ legal_questions: false,
+ legal_sow_questions: false,
+ legal_vendor_single_country: false,
+ legal_vendor_services_where_row: false,
+ sec_review_questions: false,
+ privacy_policy_project_questions: false,
+ privacy_policy_vendor_questions: false,
+ data_safety_questions: false,
+ data_safety_extra_questions: false,
+ mozilla_project_row: false,
+ privacy_policy_project_link_row: false,
+ privacy_policy_project_user_data_bug_row: false,
+ privacy_policy_vendor_extra: false,
+ data_safety_extra_questions: false,
+ data_safety_retention_length_row: false,
+ data_safety_separate_party_data_row: false,
+ data_safety_communication_channels_row: false,
+ data_safety_communication_plan_row: false,
+ };
+
+ if (Dom.get('key_initiative').value == 'Other') {
+ page_sections.key_initiative_other_row = true;
+ }
+
+ if (Dom.get('new_or_change').value == 'Existing') {
+ page_sections.mozilla_project_row = true;
+ }
+
+ if (Dom.get('new_or_change').value == 'New')
+ page_sections.legal_questions = true;
+
+ if (Dom.get('mozilla_data').value == 'Yes') {
+ page_sections.legal_questions = true;
+ page_sections.privacy_policy_project_questions = true;
+ page_sections.data_safety_questions = true;
+ page_sections.sec_review_questions = true;
+ }
+
+ if (Dom.get('separate_party').value == 'Yes') {
+ page_sections.initial_separate_party_questions = true;
+
+ if (Dom.get('relationship_type').value
+ && Dom.get('relationship_type').value != 'Hardware Purchase')
+ {
+ page_sections.legal_questions = true;
+ }
+
+ if (Dom.get('relationship_type').value == 'Vendor/Services'
+ || Dom.get('relationship_type').value == 'Distribution/Bundling')
+ {
+ page_sections.legal_sow_questions = true;
+ page_sections.legal_vendor_services_where_row = true;
+ }
+
+ if (Dom.get('relationship_type').value == 'Hardware Purchase') {
+ page_sections.finance_questions = true;
+ }
+
+ if (Dom.get('data_access').value == 'Yes') {
+ page_sections.legal_questions = true;
+ page_sections.sec_review_questions = true;
+ page_sections.privacy_policy_vendor_questions = true;
+ }
+
+ if (Dom.get('vendor_cost').value == '<= $25,000') {
+ page_sections.po_needed_row = true;
+ }
+
+ if (Dom.get('po_needed').value == 'Yes') {
+ page_sections.finance_questions = true;
+ }
+
+ if (Dom.get('vendor_cost').value == '> $25,000') {
+ page_sections.finance_questions = true;
+ }
+ }
+
+ if (Dom.get('legal_vendor_services_where').value == 'A single country') {
+ page_sections.legal_vendor_single_country = true;
+ }
+
+ if (Dom.get('finance_purchase_inbudget').value == 'No') {
+ page_sections.finance_purchase_notinbudget_why_row = true;
+ }
+
+ if (Dom.get('privacy_policy_project').value == 'Yes') {
+ page_sections.privacy_policy_project_link_row = true;
+ }
+
+ if (Dom.get('privacy_policy_user_data').value == 'Yes') {
+ page_sections.privacy_policy_project_user_data_bug_row = true;
+ }
+
+ if (Dom.get('privacy_policy_vendor_user_data').value == 'Yes') {
+ page_sections.privacy_policy_vendor_extra = true;
+ }
+
+ if (Dom.get('data_safety_user_data').value == 'Yes') {
+ page_sections.data_safety_extra_questions = true;
+ }
+
+ if (Dom.get('data_safety_retention').value == 'Yes') {
+ page_sections.data_safety_retention_length_row = true;
+ }
+
+ if (Dom.get('data_safety_separate_party').value == 'Yes') {
+ page_sections.data_safety_separate_party_data_row = true;
+ }
+
+ if (Dom.get('data_safety_community_visibility').value == 'Yes') {
+ page_sections.data_safety_communication_channels_row = true;
+ }
+
+ if (Dom.get('data_safety_community_visibility').value == 'No') {
+ page_sections.data_safety_communication_plan_row = true;
+ }
+
+ // Toggle the individual page_sections
+ for (section in page_sections) {
+ MPR.toggleShowSection(section, page_sections[section]);
+ }
+ },
+
+ toggleShowSection: function (section, show) {
+ if (show) {
+ Dom.removeClass(section, 'bz_default_hidden');
+ }
+ else {
+ Dom.addClass(section ,'bz_default_hidden');
+ }
+ },
+
+ validateAndSubmit: function () {
+ var alert_text = '';
+ var section = '';
+ for (section in this.required_fields) {
+ if (!Dom.hasClass(section, 'bz_default_hidden')) {
+ var field = '';
+ for (field in MPR.required_fields[section]) {
+ if (!MPR.isFilledOut(field)) {
+ alert_text += this.required_fields[section][field] + "\n";
+ }
+ }
+ }
+ }
+
+ // Special case checks
+ if (Dom.get('relationship_type').value == 'Vendor/Services'
+ && Dom.get('legal_vendor_services_where').value == '')
+ {
+ alert_text += "Please select a value for vendor services where\n";
+ }
+
+ if (Dom.get('relationship_type').value == 'Vendor/Services'
+ && Dom.get('legal_vendor_services_where').value == 'A single country'
+ && Dom.get('legal_vendor_single_country').value == '')
+ {
+ alert_text += "Please select a value for vendor services where single country\n";
+ }
+
+ if (Dom.get('key_initiative').value == 'Other') {
+ if (!MPR.isFilledOut('key_initiative_other')) {
+ alert_text += "Please enter a value for key initiative in the initial questions section\n";
+ }
+ }
+
+ if (Dom.get('separate_party').value == 'Yes') {
+ if (!MPR.isFilledOut('relationship_type')) {
+ alert_text += "Please select a value for type of relationship\n";
+ }
+ if (!MPR.isFilledOut('data_access')) {
+ alert_text += "Please select a value for data access\n";
+ }
+ if (!MPR.isFilledOut('vendor_cost')) {
+ alert_text += "Please select a value for vendor cost\n";
+ }
+ }
+
+ if (Dom.get('finance_purchase_inbudget').value == 'No') {
+ if (!MPR.isFilledOut('finance_purchase_notinbudget_why')) {
+ alert_text += "Please include additional description for the out of budget line item\n";
+ }
+ }
+
+ if (Dom.get('vendor_cost').value == '<= $25,000'
+ && Dom.get('po_needed').value == '')
+ {
+ alert_text += "Please select whether a PO is needed or not\n";
+ }
+
+ if (alert_text) {
+ alert(alert_text);
+ return false;
+ }
+
+ return true;
+ },
+
+ //Takes a DOM element id and makes sure that it is filled out
+ isFilledOut: function (elem_id) {
+ var str = Dom.get(elem_id).value;
+ return str.length > 0 ? true : false;
+ }
+};
+
+Event.onDOMReady(MPR.init());
diff --git a/extensions/MozProjectReview/web/style/moz_project_review.css b/extensions/MozProjectReview/web/style/moz_project_review.css
new file mode 100644
index 000000000..cf1c3a8b8
--- /dev/null
+++ b/extensions/MozProjectReview/web/style/moz_project_review.css
@@ -0,0 +1,48 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+.header {
+ width: 95%;
+ border-bottom: 1px solid rgb(116,126,147);
+ font-size: 1.5em;
+ color: rgb(102, 100, 88);
+ padding-bottom: 5px;
+ margin-bottom: 5px;
+ margin-top: 12px;
+}
+
+.field_row {
+ width: 100%;
+ min-width: 700px;
+ clear: both;
+}
+
+.field_label {
+ float: left;
+ width: 20%;
+}
+
+.field_data {
+ float: left;
+ width: 75%;
+ margin-left: 5px;
+ margin-bottom: 5px;
+}
+
+.field_description {
+ font-style: italic;
+ font-size: 90%;
+ color: rgb(102, 100, 88);
+}
+
+span.required:before {
+ content: "* ";
+}
+
+span.required:before, span.required_star {
+ color: red;
+}
diff --git a/extensions/MyDashboard/Config.pm b/extensions/MyDashboard/Config.pm
new file mode 100644
index 000000000..7c14936ff
--- /dev/null
+++ b/extensions/MyDashboard/Config.pm
@@ -0,0 +1,14 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::MyDashboard;
+
+use strict;
+
+use constant NAME => 'MyDashboard';
+
+__PACKAGE__->NAME;
diff --git a/extensions/MyDashboard/Extension.pm b/extensions/MyDashboard/Extension.pm
new file mode 100644
index 000000000..082f1c562
--- /dev/null
+++ b/extensions/MyDashboard/Extension.pm
@@ -0,0 +1,126 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::MyDashboard;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Search::Saved;
+
+use Bugzilla::Extension::MyDashboard::Queries qw(QUERY_DEFS);
+
+our $VERSION = BUGZILLA_VERSION;
+
+################
+# Installation #
+################
+
+sub db_schema_abstract_schema {
+ my ($self, $args) = @_;
+
+ my $schema = $args->{schema};
+
+ $schema->{'mydashboard'} = {
+ FIELDS => [
+ namedquery_id => {TYPE => 'INT3', NOTNULL => 1,
+ REFERENCES => {TABLE => 'namedqueries',
+ COLUMN => 'id',
+ DELETE => 'CASCADE'}},
+ user_id => {TYPE => 'INT3', NOTNULL => 1,
+ REFERENCES => {TABLE => 'profiles',
+ COLUMN => 'userid',
+ DELETE => 'CASCADE'}},
+ ],
+ INDEXES => [
+ mydashboard_namedquery_id_idx => {FIELDS => [qw(namedquery_id user_id)],
+ TYPE => 'UNIQUE'},
+ mydashboard_user_id_idx => ['user_id'],
+ ],
+ };
+}
+
+###########
+# Objects #
+###########
+
+BEGIN {
+ *Bugzilla::Search::Saved::in_mydashboard = \&_in_mydashboard;
+}
+
+sub _in_mydashboard {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $self->{'in_mydashboard'} if exists $self->{'in_mydashboard'};
+ $self->{'in_mydashboard'} = $dbh->selectrow_array("
+ SELECT 1 FROM mydashboard WHERE namedquery_id = ? AND user_id = ?",
+ undef, $self->id, Bugzilla->user->id);
+ return $self->{'in_mydashboard'};
+}
+
+#############
+# Templates #
+#############
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ return if $page ne 'mydashboard.html';
+
+ # require user to be logged in for this page
+ Bugzilla->login(LOGIN_REQUIRED);
+
+ $vars->{queries} = [ QUERY_DEFS ];
+}
+
+#########
+# Hooks #
+#########
+
+sub user_preferences {
+ my ($self, $args) = @_;
+ my $tab = $args->{'current_tab'};
+ return unless $tab eq 'saved-searches';
+
+ my $save = $args->{'save_changes'};
+ my $handled = $args->{'handled'};
+ my $vars = $args->{'vars'};
+
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $params = Bugzilla->input_params;
+
+ if ($save) {
+ my $sth_insert_fp = $dbh->prepare('INSERT INTO mydashboard
+ (namedquery_id, user_id)
+ VALUES (?, ?)');
+ my $sth_delete_fp = $dbh->prepare('DELETE FROM mydashboard
+ WHERE namedquery_id = ?
+ AND user_id = ?');
+ foreach my $q (@{$user->queries}) {
+ if (defined $params->{'in_mydashboard_' . $q->id}) {
+ $sth_insert_fp->execute($q->id, $user->id) if !$q->in_mydashboard;
+ }
+ else {
+ $sth_delete_fp->execute($q->id, $user->id) if $q->in_mydashboard;
+ }
+ }
+ }
+}
+
+sub webservice {
+ my ($self, $args) = @_;
+ my $dispatch = $args->{dispatch};
+ $dispatch->{MyDashboard} = "Bugzilla::Extension::MyDashboard::WebService";
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/MyDashboard/lib/Queries.pm b/extensions/MyDashboard/lib/Queries.pm
new file mode 100644
index 000000000..69af01d79
--- /dev/null
+++ b/extensions/MyDashboard/lib/Queries.pm
@@ -0,0 +1,259 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::MyDashboard::Queries;
+
+use strict;
+
+use Bugzilla;
+use Bugzilla::Bug;
+use Bugzilla::CGI;
+use Bugzilla::Search;
+use Bugzilla::Flag;
+use Bugzilla::Status qw(is_open_state);
+use Bugzilla::Util qw(format_time datetime_from);
+
+use Bugzilla::Extension::MyDashboard::Util qw(open_states quoted_open_states);
+use Bugzilla::Extension::MyDashboard::TimeAgo qw(time_ago);
+
+use DateTime;
+
+use base qw(Exporter);
+our @EXPORT = qw(
+ QUERY_ORDER
+ SELECT_COLUMNS
+ QUERY_DEFS
+ query_bugs
+ query_flags
+);
+
+# Default sort order
+use constant QUERY_ORDER => ("changeddate desc", "bug_id");
+
+# List of columns that we will be selecting. In the future this should be configurable
+# Share with buglist.cgi?
+use constant SELECT_COLUMNS => qw(
+ bug_id
+ bug_status
+ short_desc
+ changeddate
+);
+
+sub QUERY_DEFS {
+ my $user = Bugzilla->user;
+
+ my @query_defs = (
+ {
+ name => 'assignedbugs',
+ heading => 'Assigned to You',
+ description => 'The bug has been assigned to you and it is not resolved or closed yet.',
+ params => {
+ 'bug_status' => ['__open__'],
+ 'emailassigned_to1' => 1,
+ 'emailtype1' => 'exact',
+ 'email1' => $user->login
+ }
+ },
+ {
+ name => 'newbugs',
+ heading => 'New Reported by You',
+ description => 'You reported the bug but nobody has accepted it yet.',
+ params => {
+ 'bug_status' => ['UNCONFIRMED', 'NEW'],
+ 'emailreporter1' => 1,
+ 'emailtype1' => 'exact',
+ 'email1' => $user->login
+ }
+ },
+ {
+ name => 'inprogressbugs',
+ heading => "In Progress Reported by You",
+ description => 'You reported the bug, the developer accepted the bug and is hopefully working on it.',
+ params => {
+ 'bug_status' => [ map { $_->name } grep($_->name ne 'UNCONFIRMED' && $_->name ne 'NEW', open_states()) ],
+ 'emailreporter1' => 1,
+ 'emailtype1' => 'exact',
+ 'email1' => $user->login
+ }
+ },
+ {
+ name => 'openccbugs',
+ heading => "You Are CC'd On",
+ description => 'You are in the CC list of the bug, so you are watching it.',
+ params => {
+ 'bug_status' => ['__open__'],
+ 'emailcc1' => 1,
+ 'emailtype1' => 'exact',
+ 'email1' => $user->login
+ }
+ },
+ );
+
+ if (Bugzilla->params->{'useqacontact'}) {
+ push(@query_defs, {
+ name => 'qacontactbugs',
+ heading => 'You Are QA Contact',
+ description => 'You are the qa contact on this bug and it is not resolved or closed yet.',
+ params => {
+ 'bug_status' => ['__open__'],
+ 'emailqa_contact1' => 1,
+ 'emailtype1' => 'exact',
+ 'email1' => $user->login
+ }
+ });
+ }
+
+ if ($user->showmybugslink) {
+ my $query = Bugzilla->params->{mybugstemplate};
+ my $login = $user->login;
+ $query =~ s/%userid%/$login/;
+ $query =~ s/^buglist.cgi\?//;
+ push(@query_defs, {
+ name => 'mybugs',
+ heading => "My Bugs",
+ saved => 1,
+ params => $query,
+ });
+ }
+
+ foreach my $q (@{$user->queries}) {
+ next if !$q->in_mydashboard;
+ push(@query_defs, { name => $q->name,
+ saved => 1,
+ params => $q->url });
+ }
+
+ return @query_defs;
+}
+
+sub query_bugs {
+ my $qdef = shift;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $date_now = DateTime->now(time_zone => $user->timezone);
+
+ ## HACK to remove POST
+ delete $ENV{REQUEST_METHOD};
+
+ my $params = new Bugzilla::CGI($qdef->{params});
+
+ my $search = new Bugzilla::Search( fields => [ SELECT_COLUMNS ],
+ params => scalar $params->Vars,
+ order => [ QUERY_ORDER ]);
+ my $data = $search->data;
+
+ my @bugs;
+ foreach my $row (@$data) {
+ my $bug = {};
+ foreach my $column (SELECT_COLUMNS) {
+ $bug->{$column} = shift @$row;
+ if ($column eq 'changeddate') {
+ $bug->{$column} = format_time($bug->{$column});
+ my $date_then = datetime_from($bug->{$column});
+ $bug->{'changeddate_fancy'} = time_ago($date_then, $date_now);
+ }
+ }
+ push(@bugs, $bug);
+ }
+
+ return (\@bugs, $params->canonicalise_query());
+}
+
+sub query_flags {
+ my ($type, $include_closed) = @_;
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->dbh;
+ my $date_now = DateTime->now(time_zone => $user->timezone);
+
+ ($type ne 'requestee' || $type ne 'requester')
+ || ThrowCodeError('param_required', { param => 'type' });
+
+ my $match_params = { status => '?' };
+
+ if ($type eq 'requestee') {
+ $match_params->{'requestee_id'} = $user->id;
+ }
+ else {
+ $match_params->{'setter_id'} = $user->id;
+ }
+
+ my $matched = Bugzilla::Flag->match($match_params);
+
+ return [] if !@$matched;
+
+ my @unfiltered_flags;
+ my %all_bugs; # Use hash to filter out duplicates
+ foreach my $flag (@$matched) {
+ next if ($flag->attach_id && $flag->attachment->isprivate && !$user->is_insider);
+
+ my $data = {
+ id => $flag->id,
+ type => $flag->type->name,
+ status => $flag->status,
+ attach_id => $flag->attach_id,
+ is_patch => $flag->attach_id ? $flag->attachment->ispatch : 0,
+ bug_id => $flag->bug_id,
+ requester => $flag->setter->login,
+ requestee => $flag->requestee ? $flag->requestee->login : '',
+ updated => $flag->modification_date,
+ };
+ push(@unfiltered_flags, $data);
+
+ # Record bug id for later retrieval of status/summary
+ $all_bugs{$flag->{'bug_id'}}++;
+ }
+
+ # Filter the bug list based on permission to see the bug
+ my %visible_bugs = map { $_ => 1 } @{ $user->visible_bugs([ keys %all_bugs ]) };
+
+ return [] if !scalar keys %visible_bugs;
+
+ # Get all bug statuses and summaries in one query instead of loading
+ # many separate bug objects
+ my $bug_rows = $dbh->selectall_arrayref("SELECT bug_id, bug_status, short_desc
+ FROM bugs
+ WHERE " . $dbh->sql_in('bug_id', [ keys %visible_bugs ]),
+ { Slice => {} });
+ foreach my $row (@$bug_rows) {
+ $visible_bugs{$row->{'bug_id'}} = {
+ bug_status => $row->{'bug_status'},
+ short_desc => $row->{'short_desc'}
+ };
+ }
+
+ # Now drop out any flags for bugs the user cannot see
+ # or if the user did not want to see closed bugs
+ my @filtered_flags;
+ foreach my $flag (@unfiltered_flags) {
+ # Skip this flag if the bug is not visible to the user
+ next if !$visible_bugs{$flag->{'bug_id'}};
+
+ # Skip closed unless user requested closed bugs
+ next if (!$include_closed
+ && !is_open_state($visible_bugs{$flag->{'bug_id'}}->{'bug_status'}));
+
+ # Include bug status and summary with each flag
+ $flag->{'bug_status'} = $visible_bugs{$flag->{'bug_id'}}->{'bug_status'};
+ $flag->{'bug_summary'} = $visible_bugs{$flag->{'bug_id'}}->{'short_desc'};
+
+ # Format the updated date specific to the user's timezone
+ # and add the fancy human readable version
+ $flag->{'updated'} = format_time($flag->{'updated'});
+ my $date_then = datetime_from($flag->{'updated'});
+ $flag->{'updated_epoch'} = $date_then->epoch;
+ $flag->{'updated_fancy'} = time_ago($date_then, $date_now);
+
+ push(@filtered_flags, $flag);
+ }
+
+ return [] if !@filtered_flags;
+
+ # Sort by most recently updated
+ return [ sort { $b->{'updated_epoch'} <=> $a->{'updated_epoch'} } @filtered_flags ];
+}
+
+1;
diff --git a/extensions/MyDashboard/lib/TimeAgo.pm b/extensions/MyDashboard/lib/TimeAgo.pm
new file mode 100644
index 000000000..78badf5fa
--- /dev/null
+++ b/extensions/MyDashboard/lib/TimeAgo.pm
@@ -0,0 +1,179 @@
+package Bugzilla::Extension::MyDashboard::TimeAgo;
+
+use strict;
+use utf8;
+use DateTime;
+use Carp;
+use Exporter qw(import);
+
+use if $ENV{ARCH_64BIT}, 'integer';
+
+our @EXPORT_OK = qw(time_ago);
+
+our $VERSION = '0.06';
+
+my @ranges = (
+ [ -1, 'in the future' ],
+ [ 60, 'just now' ],
+ [ 900, 'a few minutes ago'], # 15*60
+ [ 3000, 'less than an hour ago'], # 50*60
+ [ 4500, 'about an hour ago'], # 75*60
+ [ 7200, 'more than an hour ago'], # 2*60*60
+ [ 21600, 'several hours ago'], # 6*60*60
+ [ 86400, 'today', sub { # 24*60*60
+ my $time = shift;
+ my $now = shift;
+ if ( $time->day < $now->day
+ or $time->month < $now->month
+ or $time->year < $now->year
+ ) {
+ return 'yesterday'
+ }
+ if ($time->hour < 5) {
+ return 'tonight'
+ }
+ if ($time->hour < 10) {
+ return 'this morning'
+ }
+ if ($time->hour < 15) {
+ return 'today'
+ }
+ if ($time->hour < 19) {
+ return 'this afternoon'
+ }
+ return 'this evening'
+ }],
+ [ 172800, 'yesterday'], # 2*24*60*60
+ [ 604800, 'this week'], # 7*24*60*60
+ [ 1209600, 'last week'], # 2*7*24*60*60
+ [ 2678400, 'this month', sub { # 31*24*60*60
+ my $time = shift;
+ my $now = shift;
+ if ($time->year == $now->year and $time->month == $now->month) {
+ return 'this month'
+ }
+ return 'last month'
+ }],
+ [ 5356800, 'last month'], # 2*31*24*60*60
+ [ 24105600, 'several months ago'], # 9*31*24*60*60
+ [ 31536000, 'about a year ago'], # 365*24*60*60
+ [ 34214400, 'last year'], # (365+31)*24*60*60
+ [ 63072000, 'more than a year ago'], # 2*365*24*60*60
+ [ 283824000, 'several years ago'], # 9*365*24*60*60
+ [ 315360000, 'about a decade ago'], # 10*365*24*60*60
+ [ 630720000, 'last decade'], # 20*365*24*60*60
+ [ 2838240000, 'several decades ago'], # 90*365*24*60*60
+ [ 3153600000, 'about a century ago'], # 100*365*24*60*60
+ [ 6307200000, 'last century'], # 200*365*24*60*60
+ [ 6622560000, 'more than a century ago'], # 210*365*24*60*60
+ [ 28382400000, 'several centuries ago'], # 900*365*24*60*60
+ [ 31536000000, 'about a millenium ago'], # 1000*365*24*60*60
+ [ 63072000000, 'more than a millenium ago'], # 2000*365*24*60*60
+);
+
+sub time_ago {
+ my ($time, $now) = @_;
+
+ if (not defined $time or not $time->isa('DateTime')) {
+ croak('DateTime::Duration::Fuzzy::time_ago needs a DateTime object as first parameter')
+ }
+ if (not defined $now) {
+ $now = DateTime->now();
+ }
+ if (not $now->isa('DateTime')) {
+ croak('Invalid second parameter provided to DateTime::Duration::Fuzzy::time_ago; it must be a DateTime object if provided')
+ }
+
+ my $dur = $now->subtract_datetime_absolute($time)->in_units('seconds');
+
+ foreach my $range ( @ranges ) {
+ if ( $dur <= $range->[0] ) {
+ if ( $range->[2] ) {
+ return $range->[2]->($time, $now)
+ }
+ return $range->[1]
+ }
+ }
+
+ return 'millenia ago'
+}
+
+1
+
+__END__
+
+=head1 NAME
+
+DateTime::Duration::Fuzzy -- express dates as fuzzy human-friendly strings
+
+=head1 SYNOPSIS
+
+ use DateTime::Duration::Fuzzy qw(time_ago);
+ use DateTime;
+
+ my $now = DateTime->new(
+ year => 2010, month => 12, day => 12,
+ hour => 19, minute => 59,
+ );
+ my $then = DateTime->new(
+ year => 2010, month => 12, day => 12,
+ hour => 15,
+ );
+ print time_ago($then, $now);
+ # outputs 'several hours ago'
+
+ print time_ago($then);
+ # $now taken from C<time> function
+
+=head1 DESCRIPTION
+
+DateTime::Duration::Fuzzy is inspired from the timeAgo jQuery module
+L<http://timeago.yarp.com/>.
+
+It takes two DateTime objects -- first one representing a moment in the past
+and second optional one representine the present, and returns a human-friendly
+fuzzy expression of the time gone.
+
+=head2 functions
+
+=over 4
+
+=item time_ago($then, $now)
+
+The only exportable function.
+
+First obligatory parameter is a DateTime object.
+
+Second optional parameter is also a DateTime object.
+If it's not provided, then I<now> as the C<time> function returns is
+substituted.
+
+Returns a string expression of the interval between the two DateTime
+objects, like C<several hours ago>, C<yesterday> or <last century>.
+
+=back
+
+=head2 performance
+
+On 64bit machines, it is asvisable to 'use integer', which makes
+the calculations faster. You can turn this on by setting the
+C<ARCH_64BIT> environmental variable to a true value.
+
+If you do this on a 32bit machine, you will get wrong results for
+intervals starting with "several decades ago".
+
+=head1 AUTHOR
+
+Jan Oldrich Kruza, C<< <sixtease at cpan.org> >>
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright 2010 Jan Oldrich Kruza.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of either: the GNU General Public License as published
+by the Free Software Foundation; or the Artistic License.
+
+See http://dev.perl.org/licenses/ for more information.
+
+=cut
diff --git a/extensions/MyDashboard/lib/Util.pm b/extensions/MyDashboard/lib/Util.pm
new file mode 100644
index 000000000..fa7cf83b0
--- /dev/null
+++ b/extensions/MyDashboard/lib/Util.pm
@@ -0,0 +1,50 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::MyDashboard::Util;
+
+use strict;
+
+use Bugzilla::CGI;
+use Bugzilla::Search;
+use Bugzilla::Status;
+
+use base qw(Exporter);
+@Bugzilla::Extension::MyDashboard::Util::EXPORT = qw(
+ open_states
+ closed_states
+ quoted_open_states
+ quoted_closed_states
+);
+
+our $_open_states;
+sub open_states {
+ $_open_states ||= Bugzilla::Status->match({ is_open => 1, isactive => 1 });
+ return wantarray ? @$_open_states : $_open_states;
+}
+
+our $_quoted_open_states;
+sub quoted_open_states {
+ my $dbh = Bugzilla->dbh;
+ $_quoted_open_states ||= [ map { $dbh->quote($_->name) } open_states() ];
+ return wantarray ? @$_quoted_open_states : $_quoted_open_states;
+}
+
+our $_closed_states;
+sub closed_states {
+ $_closed_states ||= Bugzilla::Status->match({ is_open => 0, isactive => 1 });
+ return wantarray ? @$_closed_states : $_closed_states;
+}
+
+our $_quoted_closed_states;
+sub quoted_closed_states {
+ my $dbh = Bugzilla->dbh;
+ $_quoted_closed_states ||= [ map { $dbh->quote($_->name) } closed_states() ];
+ return wantarray ? @$_quoted_closed_states : $_quoted_closed_states;
+}
+
+1;
diff --git a/extensions/MyDashboard/lib/WebService.pm b/extensions/MyDashboard/lib/WebService.pm
new file mode 100644
index 000000000..69f43f322
--- /dev/null
+++ b/extensions/MyDashboard/lib/WebService.pm
@@ -0,0 +1,111 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::MyDashboard::WebService;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::WebService Bugzilla::WebService::Bug);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Util qw(detaint_natural trick_taint template_var);
+use Bugzilla::WebService::Util qw(validate);
+
+use Bugzilla::Extension::MyDashboard::Queries qw(QUERY_DEFS query_bugs query_flags);
+
+use constant READ_ONLY => qw(
+ run_bug_query
+ run_flag_query
+);
+
+sub run_bug_query {
+ my($self, $params) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->login(LOGIN_REQUIRED);
+
+ defined $params->{query}
+ || ThrowCodeError('param_required',
+ { function => 'MyDashboard.run_bug_query',
+ param => 'query' });
+
+ my $result;
+ foreach my $qdef (QUERY_DEFS) {
+ next if $qdef->{name} ne $params->{query};
+ my ($bugs, $query_string) = query_bugs($qdef);
+
+ # Add last changes to each bug
+ foreach my $b (@$bugs) {
+ my $last_changes = {};
+ my $activity = $self->history({ ids => [ $b->{bug_id} ],
+ start_time => $b->{changeddate} });
+ if (@{$activity->{bugs}[0]{history}}) {
+ my $change_set = $activity->{bugs}[0]{history}[0];
+ $last_changes->{activity} = $change_set->{changes};
+ foreach my $change (@{ $last_changes->{activity} }) {
+ $change->{field_desc}
+ = template_var('field_descs')->{$change->{field_name}} || $change->{field_name};
+ }
+ $last_changes->{email} = $change_set->{who};
+ $last_changes->{when} = $self->datetime_format_inbound($change_set->{when});
+ }
+ my $last_comment_id = $dbh->selectrow_array("
+ SELECT comment_id FROM longdescs
+ WHERE bug_id = ? AND bug_when >= ?",
+ undef, $b->{bug_id}, $b->{changeddate});
+ if ($last_comment_id) {
+ my $comments = $self->comments({ comment_ids => [ $last_comment_id ] });
+ my $comment = $comments->{comments}{$last_comment_id};
+ $last_changes->{comment} = $comment->{text};
+ $last_changes->{email} = $comment->{creator} if !$last_changes->{email};
+ $last_changes->{when}
+ = $self->datetime_format_inbound($comment->{creation_time}) if !$last_changes->{when};
+ }
+ $b->{last_changes} = $last_changes;
+ }
+
+ $query_string =~ s/^POSTDATA=&//;
+ $qdef->{bugs} = $bugs;
+ $qdef->{buffer} = $query_string;
+ $result = $qdef;
+ last;
+ }
+
+ return { result => $result };
+}
+
+sub run_flag_query {
+ my ($self, $params) =@_;
+ my $user = Bugzilla->login(LOGIN_REQUIRED);
+
+ my $type = $params->{type};
+ $type || ThrowCodeError('param_required',
+ { function => 'MyDashboard.run_flag_query',
+ param => 'type' });
+
+ my $include_closed = $params->{include_closed} || 0;
+ my $results = query_flags($type, $include_closed);
+
+ return { result => { $type => $results }};
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Extension::MyDashboard::Webservice - The MyDashboard WebServices API
+
+=head1 DESCRIPTION
+
+This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+
+=head1 METHODS
+
+See L<Bugzilla::WebService> for a description of how parameters are passed,
+and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
diff --git a/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-header.html.tmpl b/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-header.html.tmpl
new file mode 100644
index 000000000..c822ab040
--- /dev/null
+++ b/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-header.html.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<th>
+ My Dashboard
+</th>
diff --git a/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-row.html.tmpl b/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-row.html.tmpl
new file mode 100644
index 000000000..cd6a36705
--- /dev/null
+++ b/extensions/MyDashboard/template/en/default/hook/account/prefs/saved-searches-saved-row.html.tmpl
@@ -0,0 +1,15 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<td align="center">
+ <input type="checkbox"
+ name="in_mydashboard_[% q.id FILTER html %]"
+ value="1"
+ alt="[% q.name FILTER html %]"
+ [% " checked" IF q.in_mydashboard %]>
+</td>
diff --git a/extensions/MyDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl b/extensions/MyDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl
new file mode 100644
index 000000000..518743ccf
--- /dev/null
+++ b/extensions/MyDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.login %]
+ <li><span class="separator"> | </span>
+ <a href="[% urlbase FILTER none %]page.cgi?id=mydashboard.html">My Dashboard</a></li>
+[% END %]
diff --git a/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl
new file mode 100644
index 000000000..8222f6749
--- /dev/null
+++ b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl
@@ -0,0 +1,150 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "My Dashboard"
+ style_urls = [ "extensions/MyDashboard/web/styles/mydashboard.css",
+ "extensions/ProdCompSearch/web/styles/prod_comp_search.css" ]
+ javascript_urls = [ "js/yui3/yui/yui-min.js",
+ "extensions/MyDashboard/web/js/query.js",
+ "extensions/MyDashboard/web/js/flags.js",
+ "extensions/ProdCompSearch/web/js/prod_comp_search.js" ]
+%]
+
+[% standard_queries = [] %]
+[% saved_queries = [] %]
+[% FOREACH q = queries %]
+ [% standard_queries.push(q) IF !q.saved %]
+ [% saved_queries.push(q) IF q.saved %]
+[% END %]
+
+<script id="last-changes-template" type="text/x-handlebars-template">
+ <div id="last_changes">
+ {{#if email}}
+ <div id="last_changes_header">
+ Last Changes :: {{email}} :: {{when}}
+ </div>
+ {{#if activity}}
+ <table id="activity">
+ {{#each activity}}
+ <tr>
+ <td class="field_label">{{field_desc}}:</td>
+ <td class="field_data">
+ {{#if removed}}
+ {{#unless added}}
+ Removed:
+ {{/unless}}
+ {{removed}}
+ {{/if}}
+ {{#if added}}
+ {{#if removed}}
+ &rarr;
+ {{/if}}
+ {{/if}}
+ {{#if added}}
+ {{#unless removed}}
+ Added:
+ {{/unless}}
+ {{added}}
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </table>
+ {{/if}}
+ {{#if comment}}
+ <pre class='bz_comment_text'>{{comment}}</pre>
+ {{/if}}
+ {{else}}
+ This is a new [% terms.bug %] and no changes have been made yet.
+ {{/if}}
+ </div>
+</script>
+
+<script type="text/javascript">
+ [% IF Param('splinter_base') %]
+ MyDashboard.splinter_base = '[% Bugzilla.splinter_review_base FILTER js %]';
+ [% END %]
+</script>
+
+<div id="mydashboard">
+ <div class="yui3-skin-sam">
+ <div id="left">
+ <div id="query_list_container">
+ Choose query:
+ <select id="query" name="query">
+ <optgroup id="standard_queries" label="Standard">
+ [% FOREACH r = standard_queries %]
+ <option value="[% r.name FILTER html %]">[% r.heading || r.name FILTER html %]</option>
+ [% END%]
+ </optgroup>
+ <optgroup id="saved_queries" label="Saved">
+ [% FOREACH r = saved_queries %]
+ <option value="[% r.name FILTER html %]">[% r.heading || r.name FILTER html %]</option>
+ [% END %]
+ </optgroup>
+ </select>
+ <small>
+ (<a href="userprefs.cgi?tab=saved-searches">add or remove saved searches</a>)
+ </small>
+ </div>
+
+ <div id="query_container">
+ <div class="query_heading"></div>
+ <div class="query_description"></div>
+ <span id="query_count_refresh" class="bz_default_hidden">
+ <span class="items_found" id="query_bugs_found">0 [% terms.bugs %] found</span>
+ | <a class="refresh" href="javascript:void(0);" id="query_refresh">Refresh</a>
+ </span>
+ <div id="query_pagination_top"></div>
+ <div id="query_table"></div>
+ </div>
+ </div>
+
+ <div id="right">
+ <div id="prod_comp_search_main">
+ [% PROCESS prodcompsearch/form.html.tmpl
+ input_label = "File a $terms.Bug:"
+ script_name = "enter_bug.cgi"
+ new_tab = 1
+ %]
+ </div>
+
+ <div id="requestee_container">
+ <div class="query_heading">
+ Flags Requested of You
+ </div>
+ <span id="requestee_count_refresh" class="bz_default_hidden">
+ <span class="items_found" id="requestee_flags_found">0 flags found</span>
+ | <a class="refresh" href="javascript:void(0);" id="requestee_refresh">Refresh</a>
+ | <input type="checkbox" id="requestee_closed">
+ <label for="requestee_closed">Include Closed</label>
+ </span>
+ <div id="requestee_table"></div>
+ </div>
+
+ <div id="requester_container">
+ <div class="query_heading">
+ Flags You Have Requested
+ </div>
+ <span id="requester_count_refresh" class="bz_default_hidden">
+ <span class="items_found" id="requester_flags_found">0 flags found</span>
+ | <a class="refresh" href="javascript:void(0);" id="requester_refresh">Refresh</a>
+ | <input type="checkbox" id="requester_closed">
+ <label for="requester_closed">Include Closed</label>
+ </span>
+ <div id="requester_table"></div>
+ </div>
+ </div>
+ <div style="clear:both;"></div>
+ </div>
+</div>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/MyDashboard/web/js/flags.js b/extensions/MyDashboard/web/js/flags.js
new file mode 100644
index 000000000..9c4da50dc
--- /dev/null
+++ b/extensions/MyDashboard/web/js/flags.js
@@ -0,0 +1,189 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+// Flag tables
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("node", "datatable", "datatable-sort", "json-stringify", "escape",
+ "datatable-datasource", "datasource-io", "datasource-jsonschema", function (Y) {
+ // Common
+ var counter = 0;
+ var dataSource = {
+ requestee: null,
+ requester: null
+ };
+ var dataTable = {
+ requestee: null,
+ requester: null
+ };
+
+ var updateFlagTable = function (type) {
+ if (!type) return;
+
+ var include_closed = Y.one('#' + type + '_closed').get('checked') ? 1 : 0;
+
+ counter = counter + 1;
+
+ var callback = {
+ success: function(e) {
+ if (e.response) {
+ Y.one('#' + type + '_count_refresh').removeClass('bz_default_hidden');
+ Y.one("#" + type + "_flags_found").setHTML(
+ e.response.results.length + ' flags found');
+ dataTable[type].set('data', e.response.results);
+ }
+ },
+ failure: function(o) {
+ var resp = o.responseText;
+ alert("IO request failed : " + resp);
+ }
+ };
+
+ var json_object = {
+ version: "1.1",
+ method: "MyDashboard.run_flag_query",
+ id: counter,
+ params: { type : type, include_closed: include_closed }
+ };
+
+ var stringified = Y.JSON.stringify(json_object);
+
+ Y.one('#' + type + '_count_refresh').addClass('bz_default_hidden');
+
+ dataTable[type].set('data', []);
+ dataTable[type].render("#" + type + "_table");
+ dataTable[type].showMessage('loadingMessage');
+
+ dataSource[type].sendRequest({
+ request: stringified,
+ cfg: {
+ method: "POST",
+ headers: { 'Content-Type': 'application/json' }
+ },
+ callback: callback
+ });
+ };
+
+ var bugLinkFormatter = function (o) {
+ var bug_closed = "";
+ if (o.data.bug_status == 'RESOLVED' || o.data.bug_status == 'VERIFIED') {
+ bug_closed = "bz_closed";
+ }
+ return '<a href="show_bug.cgi?id=' + encodeURIComponent(o.value) +
+ '" target="_blank" ' + 'title="' + Y.Escape.html(o.data.bug_status) + ' - ' +
+ Y.Escape.html(o.data.bug_summary) + '" class="' + Y.Escape.html(bug_closed) +
+ '">' + o.value + '</a>';
+ };
+
+ var updatedFormatter = function (o) {
+ return '<span title="' + Y.Escape.html(o.value) + '">' +
+ Y.Escape.html(o.data.updated_fancy) + '</span>';
+ };
+
+ var requesteeFormatter = function (o) {
+ return o.value
+ ? Y.Escape.html(o.value)
+ : '<i>anyone</i>';
+ };
+
+ var flagNameFormatter = function (o) {
+ if (o.data.attach_id && o.data.is_patch && MyDashboard.splinter_base) {
+ return '<a href="' + MyDashboard.splinter_base +
+ (MyDashboard.splinter_base.indexOf('?') == -1 ? '?' : '&') +
+ 'bug=' + encodeURIComponent(o.data.bug_id) +
+ '&attachment=' + encodeURIComponent(o.data.attach_id) +
+ '" target="_blank" title="Review this patch">' +
+ Y.Escape.html(o.value) + '</a>';
+ }
+ else {
+ return Y.Escape.html(o.value);
+ }
+ };
+
+ // Requestee
+ dataSource.requestee = new Y.DataSource.IO({ source: 'jsonrpc.cgi' });
+ dataTable.requestee = new Y.DataTable({
+ columns: [
+ { key: "requester", label: "Requester", sortable: true },
+ { key: "type", label: "Flag", sortable: true,
+ formatter: flagNameFormatter, allowHTML: true },
+ { key: "bug_id", label: "Bug", sortable: true,
+ formatter: bugLinkFormatter, allowHTML: true },
+ { key: "updated", label: "Updated", sortable: true,
+ formatter: updatedFormatter, allowHTML: true }
+ ],
+ strings: {
+ emptyMessage: 'No flag data found.',
+ }
+ });
+
+ dataTable.requestee.plug(Y.Plugin.DataTableSort);
+
+ dataTable.requestee.plug(Y.Plugin.DataTableDataSource, {
+ datasource: dataSource,
+ initialRequest: updateFlagTable("requestee"),
+ });
+
+ dataSource.requestee.plug(Y.Plugin.DataSourceJSONSchema, {
+ schema: {
+ resultListLocator: "result.result.requestee",
+ resultFields: ["requester", "type", "attach_id", "is_patch", "bug_id",
+ "bug_status", "bug_summary", "updated", "updated_fancy"]
+ }
+ });
+
+ dataTable.requestee.render("#requestee_table");
+
+ Y.one('#requestee_refresh').on('click', function(e) {
+ updateFlagTable('requestee');
+ });
+ Y.one('#requestee_closed').on('change', function(e) {
+ updateFlagTable('requestee');
+ });
+
+ // Requester
+ dataSource.requester = new Y.DataSource.IO({ source: 'jsonrpc.cgi' });
+ dataTable.requester = new Y.DataTable({
+ columns: [
+ { key:"requestee", label:"Requestee", sortable:true,
+ formatter: requesteeFormatter, allowHTML: true },
+ { key:"type", label:"Flag", sortable:true,
+ formatter: flagNameFormatter, allowHTML: true },
+ { key:"bug_id", label:"Bug", sortable:true,
+ formatter: bugLinkFormatter, allowHTML: true },
+ { key: "updated", label: "Updated", sortable: true,
+ formatter: updatedFormatter, allowHTML: true }
+ ],
+ strings: {
+ emptyMessage: 'No flag data found.',
+ }
+ });
+
+ dataTable.requester.plug(Y.Plugin.DataTableSort);
+
+ dataTable.requester.plug(Y.Plugin.DataTableDataSource, {
+ datasource: dataSource,
+ initialRequest: updateFlagTable("requester"),
+ });
+
+ dataSource.requester.plug(Y.Plugin.DataSourceJSONSchema, {
+ schema: {
+ resultListLocator: "result.result.requester",
+ resultFields: ["requestee", "type", "attach_id", "is_patch", "bug_id",
+ "bug_status", "bug_summary", "updated", "updated_fancy"]
+ }
+ });
+
+ Y.one('#requester_refresh').on('click', function(e) {
+ updateFlagTable('requester');
+ });
+ Y.one('#requester_closed').on('change', function(e) {
+ updateFlagTable('requester');
+ });
+});
diff --git a/extensions/MyDashboard/web/js/query.js b/extensions/MyDashboard/web/js/query.js
new file mode 100644
index 000000000..7d25cc33e
--- /dev/null
+++ b/extensions/MyDashboard/web/js/query.js
@@ -0,0 +1,167 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+if (typeof(MyDashboard) == 'undefined') {
+ var MyDashboard = {};
+}
+
+// Main query code
+YUI({
+ base: 'js/yui3/',
+ combine: false,
+ groups: {
+ gallery: {
+ combine: false,
+ base: 'js/yui3/',
+ patterns: { 'gallery-': {} }
+ }
+ }
+}).use("node", "datatable", "datatable-sort", "datatable-message", "json-stringify",
+ "datatable-datasource", "datasource-io", "datasource-jsonschema", "cookie",
+ "gallery-datatable-row-expansion-bmo", "handlebars", "escape", function (Y) {
+ var counter = 0,
+ dataSource = null,
+ dataTable = null,
+ default_query = "assignedbugs";
+
+ // Grab last used query name from cookie or use default
+ var query_cookie = Y.Cookie.get("my_dashboard_query");
+ if (query_cookie) {
+ var cookie_value_found = 0;
+ Y.one("#query").get("options").each( function() {
+ if (this.get("value") == query_cookie) {
+ this.set('selected', true);
+ default_query = query_cookie;
+ cookie_value_found = 1;
+ }
+ });
+ if (!cookie_value_found) {
+ Y.Cookie.set("my_dashboard_query", "");
+ }
+ }
+
+ var updateQueryTable = function(query_name) {
+ if (!query_name) return;
+
+ counter = counter + 1;
+
+ var callback = {
+ success: function(e) {
+ if (e.response) {
+ Y.one('#query_count_refresh').removeClass('bz_default_hidden');
+ Y.one("#query_container .query_description").setHTML(e.response.meta.description);
+ Y.one("#query_container .query_heading").setHTML(e.response.meta.heading);
+ Y.one("#query_bugs_found").setHTML(
+ '<a href="buglist.cgi?' + e.response.meta.buffer +
+ '" target="_blank">' + e.response.results.length + ' bugs found</a>');
+ dataTable.set('data', e.response.results);
+ }
+ },
+ failure: function(o) {
+ var resp = o.responseText;
+ alert("IO request failed : " + resp);
+ }
+ };
+
+ var json_object = {
+ version: "1.1",
+ method: "MyDashboard.run_bug_query",
+ id: counter,
+ params: { query : query_name }
+ };
+
+ var stringified = Y.JSON.stringify(json_object);
+
+ Y.one('#query_count_refresh').addClass('bz_default_hidden');
+
+ dataTable.set('data', []);
+ dataTable.render("#query_table");
+ dataTable.showMessage('loadingMessage');
+
+ dataSource.sendRequest({
+ request: stringified,
+ cfg: {
+ method: "POST",
+ headers: { 'Content-Type': 'application/json' }
+ },
+ callback: callback
+ });
+ };
+
+ var updatedFormatter = function (o) {
+ return '<span title="' + Y.Escape.html(o.value) + '">' +
+ Y.Escape.html(o.data.changeddate_fancy) + '</span>';
+ };
+
+ dataSource = new Y.DataSource.IO({ source: 'jsonrpc.cgi' });
+
+ dataSource.plug(Y.Plugin.DataSourceJSONSchema, {
+ schema: {
+ resultListLocator: "result.result.bugs",
+ resultFields: ["bug_id", "changeddate", "changeddate_fancy",
+ "bug_status", "short_desc", "last_changes"],
+ metaFields: {
+ description: "result.result.description",
+ heading: "result.result.heading",
+ buffer: "result.result.buffer"
+ }
+ }
+ });
+
+ dataTable = new Y.DataTable({
+ columns: [
+ { key: Y.Plugin.DataTableRowExpansion.column_key, label: ' ', sortable: false },
+ { key: "bug_id", label: "Bug", allowHTML: true,
+ formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>' },
+ { key: "changeddate", label: "Updated", formatter: updatedFormatter, allowHTML: true },
+ { key: "bug_status", label: "Status" },
+ { key: "short_desc", label: "Summary" },
+ ],
+ sortable: true
+ });
+
+ var last_changes_source = Y.one('#last-changes-template').getHTML(),
+ last_changes_template = Y.Handlebars.compile(last_changes_source);
+
+ dataTable.plug(Y.Plugin.DataTableRowExpansion, {
+ uniqueIdKey: 'bug_id',
+ template: function(data) {
+ var last_changes = {};
+ if (data.last_changes.email) {
+ last_changes = {
+ activity: data.last_changes.activity,
+ email: data.last_changes.email,
+ when: data.last_changes.when,
+ comment: data.last_changes.comment,
+ };
+ }
+ return last_changes_template(last_changes);
+ }
+ });
+
+ dataTable.plug(Y.Plugin.DataTableSort);
+
+ dataTable.plug(Y.Plugin.DataTableDataSource, {
+ datasource: dataSource,
+ initialRequest: updateQueryTable(default_query),
+ });
+
+ Y.one('#query').on('change', function(e) {
+ var index = e.target.get('selectedIndex');
+ var selected_value = e.target.get("options").item(index).getAttribute('value');
+ updateQueryTable(selected_value);
+ Y.Cookie.set("my_dashboard_query", selected_value, { expires: new Date("January 12, 2025") });
+ });
+
+ Y.one('#query_refresh').on('click', function(e) {
+ var query_select = Y.one('#query');
+ var index = query_select.get('selectedIndex');
+ var selected_value = query_select.get("options").item(index).getAttribute('value');
+ updateQueryTable(selected_value);
+ });
+});
diff --git a/extensions/MyDashboard/web/styles/mydashboard.css b/extensions/MyDashboard/web/styles/mydashboard.css
new file mode 100644
index 000000000..050fd95c2
--- /dev/null
+++ b/extensions/MyDashboard/web/styles/mydashboard.css
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#mydashboard {
+ min-width: 900px;
+}
+
+#mydashboard .yui3-skin-sam .yui3-datatable-table {
+ width: 100%;
+}
+
+.yui3-datatable-col-changeddate,
+.yui3-datatable-col-created {
+ white-space: nowrap;
+}
+
+.query_heading {
+ font-size: 18px;
+ font-weight: strong;
+ padding-bottom: 5px;
+ padding-top: 5px;
+ color: rgb(72, 72, 72);
+}
+
+.query_description {
+ font-size: 90%;
+ font-style: italic;
+ padding-bottom: 5px;
+ color: rgb(109, 117, 129);
+}
+
+#mydashboard_container {
+ margin: 0 auto;
+}
+
+#left {
+ float: left;
+ width: 58%;
+}
+
+#right {
+ float: right;
+ width: 40%;
+}
+
+.items_found, .refresh {
+ font-size: 80%;
+}
+
+#query_list_container {
+ text-align:center;
+}
+
+#query_list_container,
+#prod_comp_search_main {
+ padding: 20px !important;
+ height: 40px;
+}
+
+#last_changes_header {
+ font-size: 12px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ border-bottom: 1px solid rgb(200, 200, 186);
+}
+
+#last_changes .field_label {
+ text-align: left;
+}
diff --git a/extensions/Needinfo/Config.pm b/extensions/Needinfo/Config.pm
new file mode 100644
index 000000000..86c99ec59
--- /dev/null
+++ b/extensions/Needinfo/Config.pm
@@ -0,0 +1,18 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::Needinfo;
+use strict;
+
+use constant NAME => 'Needinfo';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/Needinfo/Extension.pm b/extensions/Needinfo/Extension.pm
new file mode 100644
index 000000000..e88e764b2
--- /dev/null
+++ b/extensions/Needinfo/Extension.pm
@@ -0,0 +1,162 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::Needinfo;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::User;
+use Bugzilla::Flag;
+use Bugzilla::FlagType;
+
+our $VERSION = '0.01';
+
+sub install_update_db {
+ my ($self, $args) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ if (@{ Bugzilla::FlagType::match({ name => 'needinfo' }) }) {
+ return;
+ }
+
+ print "Creating needinfo flag ... " .
+ "enable the Needinfo feature by editing the flag's properties.\n";
+
+ # Initially populate the list of exclusions as __Any__:__Any__ to
+ # allow admin to decide which products to enable the flag for.
+ my $flagtype = Bugzilla::FlagType->create({
+ name => 'needinfo',
+ description => "Set this flag when the bug is in need of additional information",
+ target_type => 'bug',
+ cc_list => '',
+ sortkey => 1,
+ is_active => 1,
+ is_requestable => 1,
+ is_requesteeble => 1,
+ is_multiplicable => 0,
+ request_group => '',
+ grant_group => '',
+ inclusions => [],
+ exclusions => ['0:0'],
+ });
+}
+
+# Clear the needinfo? flag if comment is being given by
+# requestee or someone used the override flag.
+sub bug_start_of_update {
+ my ($self, $args) = @_;
+ my $bug = $args->{bug};
+ my $old_bug = $args->{old_bug};
+
+ my $user = Bugzilla->user;
+ my $cgi = Bugzilla->cgi;
+ my $params = Bugzilla->input_params;
+
+ if ($user->in_group('canconfirm') && $params->{needinfo}) {
+ # do a match if applicable
+ Bugzilla::User::match_field({
+ 'needinfo_from' => { 'type' => 'single' }
+ });
+ }
+
+ # Set needinfo_done param to true so as to not loop back here
+ return if $params->{needinfo_done};
+ $params->{needinfo_done} = 1;
+ Bugzilla->input_params($params);
+
+ my $needinfo = delete $params->{needinfo};
+ my $needinfo_from = delete $params->{needinfo_from};
+ my $needinfo_role = delete $params->{needinfo_role};
+ my $is_private = $params->{'comment_is_private'};
+
+ my @needinfo_overrides;
+ foreach my $key (grep(/^needinfo_override_/, keys %$params)) {
+ my ($id) = $key =~ /(\d+)$/;
+ # Should always be true if key exists (checkbox) but better to be sure
+ push(@needinfo_overrides, $id) if $id && $params->{$key};
+ }
+
+ # Set the needinfo flag if user is requesting more information
+ my @new_flags;
+ my $needinfo_requestee;
+
+ if ($user->in_group('canconfirm') && $needinfo) {
+ foreach my $type (@{ $bug->flag_types }) {
+ next if $type->name ne 'needinfo';
+
+ my $needinfo_flag = { type_id => $type->id, status => '?' };
+
+ # Use assigned_to as requestee
+ if ($needinfo_role eq 'assigned_to') {
+ $needinfo_flag->{requestee} = $bug->assigned_to->login;
+ }
+ # Use reporter as requestee
+ elsif ( $needinfo_role eq 'reporter') {
+ $needinfo_flag->{requestee} = $bug->reporter->login;
+ }
+ # Use qa_contact as requestee
+ elsif ($needinfo_role eq 'qa_contact') {
+ $needinfo_flag->{requestee} = $bug->qa_contact->login;
+ }
+ # Use user specified requestee
+ elsif ($needinfo_role eq 'other' && $needinfo_from) {
+ Bugzilla::User->check($needinfo_from);
+ $needinfo_flag->{requestee} = $needinfo_from;
+ }
+
+ # Find out if the requestee has already been used and skip if so
+ my $requestee_found;
+ foreach my $flag (@{ $type->{flags} }) {
+ if ((!$flag->requestee && !exists $needinfo_flag->{requestee})
+ || ($flag->requestee && exists $needinfo_flag->{requestee}
+ && $flag->requestee->login eq $needinfo_flag->{requestee}))
+ {
+ $requestee_found = 1;
+ last;
+ }
+ }
+ next if $requestee_found;
+
+ if ($needinfo) {
+ push(@new_flags, $needinfo_flag);
+ last;
+ }
+ }
+ }
+
+ # Clear the flag if additional information was given as requested
+ my @flags;
+ foreach my $flag (@{ $bug->flags }) {
+ next if $flag->type->name ne 'needinfo';
+ my $clear_needinfo = 0;
+
+ # Clear if somehow the flag has been set to +/-
+ $clear_needinfo = 1 if $flag->status ne '?';
+
+ # Clear if current user has selected override
+ $clear_needinfo = 1 if grep($_ == $flag->id, @needinfo_overrides);
+
+ # Clear if comment provided by the proper requestee
+ if ($bug->{added_comments}
+ && (!$flag->requestee || $flag->requestee->login eq Bugzilla->user->login)
+ && (!$is_private || $flag->setter->is_insider))
+ {
+ $clear_needinfo = 1;
+ }
+
+ if ($clear_needinfo) {
+ push(@flags, { id => $flag->id, status => 'X' });
+ }
+ }
+
+ if (@flags || @new_flags) {
+ $bug->set_flags(\@flags, \@new_flags);
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Needinfo/template/en/default/bug/needinfo.html.tmpl b/extensions/Needinfo/template/en/default/bug/needinfo.html.tmpl
new file mode 100644
index 000000000..6031d6e0c
--- /dev/null
+++ b/extensions/Needinfo/template/en/default/bug/needinfo.html.tmpl
@@ -0,0 +1,97 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% needinfo_flagtype = "" %]
+[% needinfo_flags = [] %]
+
+[% FOREACH type = bug.flag_types %]
+ [% IF type.name == 'needinfo' %]
+ [% needinfo_flagtype = type %]
+ [% FOREACH flag = type.flags %]
+ [% IF flag.status == '?' %]
+ [% needinfo_flags.push(flag) %]
+ [% END %]
+ [% END %]
+ [% LAST IF needinfo_flagtype %]
+ [% END %]
+[% END %]
+
+[% IF needinfo_flagtype %]
+ <div id="needinfo_container">
+ [% IF needinfo_flags.size > 0 %]
+ [%# Displays NEEDINFO tag in bug header %]
+ <script>
+ var summary_container = document.getElementById('static_bug_status');
+ summary_container.appendChild(document.createTextNode('[NEEDINFO]'));
+ </script>
+ [% END %]
+ <table>
+ [% FOREACH flag = needinfo_flags %]
+ <tr>
+ [% IF !flag.requestee || flag.requestee.id == user.id %]
+ <td align="center"><span style="color:red;font-weight:bold;">*</span></td>
+ <td>
+ Adding a comment will automatically clear needinfo the request for
+ <em>[% IF !flag.requestee %]anyone[% ELSE %][% flag.requestee.login FILTER html %][% END %]</em>.
+ </td>
+ [% ELSE %]
+ <td align="center">
+ <input type="checkbox" id="needinfo_override_[% flag.id FILTER html %]"
+ name="needinfo_override_[% flag.id FILTER html %]" value="1">
+ </td>
+ <td>
+ <label for="needinfo_override_[% flag.id FILTER html %]">
+ I am providing the requested information for <em>[% flag.requestee.login FILTER html %]</em>
+ (clears the needinfo request).
+ </label>
+ </td>
+ [% END %]
+ </tr>
+ [% END %]
+ [% IF user.in_group('canconfirm') && (needinfo_flags.size == 0 || needinfo_flagtype.is_multiplicable) %]
+ <tr>
+ <td align="center">
+ <script>
+ function needinfoRole (select) {
+ YAHOO.util.Dom.get('needinfo').checked = true;
+ if (select.value == 'other') {
+ YAHOO.util.Dom.removeClass('needinfo_from_container', 'bz_default_hidden');
+ YAHOO.util.Dom.get('needinfo_from').focus();
+ }
+ else {
+ YAHOO.util.Dom.addClass('needinfo_from_container', 'bz_default_hidden');
+ }
+ }
+ </script>
+ <input type="checkbox" name="needinfo" value="1" id="needinfo">
+ </td>
+ <td>
+ <label for="needinfo">Need more information from</label>
+ <select name="needinfo_role" id="needinfo_role" onchange="needinfoRole(this);">
+ <option value="">anyone</option>
+ <option value="reporter">reporter</option>
+ <option value="assigned_to">assignee</option>
+ [% IF Param('useqacontact') && bug.qa_contact.login != "" %]
+ <option value="qa_contact">qa contact</option>
+ [% END %]
+ <option value="other">other</option>
+ </select>
+ <span id="needinfo_from_container" class="bz_default_hidden">
+ [%+ INCLUDE global/userselect.html.tmpl
+ id => "needinfo_from"
+ name => "needinfo_from"
+ size => 30
+ value => ""
+ %]
+ </span>
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </div>
+[% END %]
diff --git a/extensions/Needinfo/template/en/default/hook/attachment/create-form_before_submit.html.tmpl b/extensions/Needinfo/template/en/default/hook/attachment/create-form_before_submit.html.tmpl
new file mode 100644
index 000000000..ea9c17bd5
--- /dev/null
+++ b/extensions/Needinfo/template/en/default/hook/attachment/create-form_before_submit.html.tmpl
@@ -0,0 +1,17 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ [% PROCESS bug/needinfo.html.tmpl
+ bug => bug
+ is_attachment => 1
+ %]
+ </td>
+</tr>
diff --git a/extensions/Needinfo/template/en/default/hook/attachment/edit-after_comment_textarea.html.tmpl b/extensions/Needinfo/template/en/default/hook/attachment/edit-after_comment_textarea.html.tmpl
new file mode 100644
index 000000000..8f03fc752
--- /dev/null
+++ b/extensions/Needinfo/template/en/default/hook/attachment/edit-after_comment_textarea.html.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS bug/needinfo.html.tmpl
+ bug => attachment.bug
+ is_attachment => 1
+%]
diff --git a/extensions/Needinfo/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl b/extensions/Needinfo/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl
new file mode 100644
index 000000000..90f0cc584
--- /dev/null
+++ b/extensions/Needinfo/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS bug/needinfo.html.tmpl
+ bug = bug
+%]
diff --git a/extensions/Needinfo/template/en/default/hook/request/email-after_summary.txt.tmpl b/extensions/Needinfo/template/en/default/hook/request/email-after_summary.txt.tmpl
new file mode 100644
index 000000000..6a302b76a
--- /dev/null
+++ b/extensions/Needinfo/template/en/default/hook/request/email-after_summary.txt.tmpl
@@ -0,0 +1,13 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS flag && flag.type.name == 'needinfo' && flag.status == '?' %]
+---
+--- This request has set a needinfo flag on the [% terms.bug %].
+--- You can clear it by logging in and replying in a comment.
+---
diff --git a/extensions/OpenGraph/Config.pm b/extensions/OpenGraph/Config.pm
new file mode 100644
index 000000000..9204db234
--- /dev/null
+++ b/extensions/OpenGraph/Config.pm
@@ -0,0 +1,16 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::OpenGraph;
+
+use strict;
+
+use constant NAME => 'OpenGraph';
+use constant REQUIRED_MODULES => [ ];
+use constant OPTIONAL_MODULES => [ ];
+
+__PACKAGE__->NAME;
diff --git a/extensions/OpenGraph/Extension.pm b/extensions/OpenGraph/Extension.pm
new file mode 100644
index 000000000..f278a8958
--- /dev/null
+++ b/extensions/OpenGraph/Extension.pm
@@ -0,0 +1,16 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::OpenGraph;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '1';
+
+__PACKAGE__->NAME;
diff --git a/extensions/OpenGraph/template/en/default/hook/global/header-start.html.tmpl b/extensions/OpenGraph/template/en/default/hook/global/header-start.html.tmpl
new file mode 100644
index 000000000..8503343df
--- /dev/null
+++ b/extensions/OpenGraph/template/en/default/hook/global/header-start.html.tmpl
@@ -0,0 +1,13 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+<meta property="og:type" content="website">
+<meta property="og:image" content="[% urlbase FILTER none %]extensions/OpenGraph/web/bugzilla.png">
+<meta property="og:title" content="[% title FILTER html %]">
+<meta property="og:url" content="[% Bugzilla.cgi.self_url FILTER none %]">
diff --git a/extensions/OpenGraph/web/bugzilla.png b/extensions/OpenGraph/web/bugzilla.png
new file mode 100644
index 000000000..55ee01210
--- /dev/null
+++ b/extensions/OpenGraph/web/bugzilla.png
Binary files differ
diff --git a/extensions/OrangeFactor/Config.pm b/extensions/OrangeFactor/Config.pm
new file mode 100644
index 000000000..9fb0d74ef
--- /dev/null
+++ b/extensions/OrangeFactor/Config.pm
@@ -0,0 +1,13 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::OrangeFactor;
+use strict;
+
+use constant NAME => 'OrangeFactor';
+
+__PACKAGE__->NAME;
diff --git a/extensions/OrangeFactor/Extension.pm b/extensions/OrangeFactor/Extension.pm
new file mode 100644
index 000000000..483a83533
--- /dev/null
+++ b/extensions/OrangeFactor/Extension.pm
@@ -0,0 +1,44 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::OrangeFactor;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::User::Setting;
+use Bugzilla::Constants;
+use Bugzilla::Attachment;
+
+our $VERSION = '1.0';
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ my $user = Bugzilla->user;
+
+ return unless $user && $user->id && $user->settings;
+ return unless $user->settings->{'orange_factor'}->{'value'} eq 'on';
+
+ # in the header we just need to set the var,
+ # to ensure the css and javascript get included
+ if ($file eq 'bug/show-header.html.tmpl'
+ || $file eq 'bug/edit.html.tmpl') {
+ my $bug = exists $vars->{'bugs'} ? $vars->{'bugs'}[0] : $vars->{'bug'};
+ if ($bug && grep($_->name eq 'intermittent-failure', @{ $bug->keyword_objects })) {
+ $vars->{'orange_factor'} = 1;
+ }
+ }
+}
+
+sub install_before_final_checks {
+ my ($self, $args) = @_;
+ add_setting('orange_factor', ['on', 'off'], 'off');
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/OrangeFactor/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/OrangeFactor/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..a41188a63
--- /dev/null
+++ b/extensions/OrangeFactor/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,26 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% IF orange_factor %]
+ <tr>
+ <th class="field_label" valign="top">
+ Orange Factor:
+ </th>
+ <td>
+ [% IF cgi.user_agent.match('(?i)gecko') %]
+ <canvas id="orange-graph" class="bz_default_hidden"></canvas>
+ <span id="orange-count"></span>
+ [% END %]
+ (<a href="https://brasstacks.mozilla.com/orangefactor/?display=Bug&bugid=[% bug.bug_id FILTER uri %]"
+ title="Click to load Orange Factor page for this [% terms.bug %]">link</a>)
+ </td>
+ </tr>
+[% END %]
diff --git a/extensions/OrangeFactor/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/OrangeFactor/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..b41431dcf
--- /dev/null
+++ b/extensions/OrangeFactor/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,17 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+[% IF orange_factor && cgi.user_agent.match('(?i)gecko') %]
+ [% style_urls.push('extensions/OrangeFactor/web/style/orangefactor.css') %]
+ [% javascript_urls.push('extensions/OrangeFactor/web/js/sparklines.min.js') %]
+ [% javascript_urls.push('extensions/OrangeFactor/web/js/orange_factor.js') %]
+[% END %]
+
diff --git a/extensions/OrangeFactor/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/OrangeFactor/template/en/default/hook/global/setting-descs-settings.none.tmpl
new file mode 100644
index 000000000..21a525deb
--- /dev/null
+++ b/extensions/OrangeFactor/template/en/default/hook/global/setting-descs-settings.none.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ setting_descs.orange_factor = "When viewing a $terms.bug, show its corresponding Orange Factor page"
+%]
diff --git a/extensions/OrangeFactor/web/js/AUTHORS.processing.js b/extensions/OrangeFactor/web/js/AUTHORS.processing.js
new file mode 100644
index 000000000..e1244b717
--- /dev/null
+++ b/extensions/OrangeFactor/web/js/AUTHORS.processing.js
@@ -0,0 +1,35 @@
+John Resig
+Alistair MacDonald
+David Humphrey
+Corban Brook
+Anna Sobiepanek
+Andor Salga
+Daniel Hodgin
+Scott Downe
+Yuri Delendik
+Mike Kamermans
+Chris Lonnen
+Mickael Medel
+Matthew Lam
+Jon Buckley
+Dominic Baranski
+Elijah Grey
+Thomas Saunders
+Abel Allison
+Andrew Grimo
+Donghui Liu
+Edward Sin
+Alex Londono
+Robert O'Rourke
+Thanh Dao
+Zhibin Huang
+John Turner
+Tom Brown
+Minoo Ziaei
+Ricard Marxer
+Matt Postill
+Tiago Moreira
+Jonathan Brodsky
+Roger Sodre
+James Boelen
+Michal Ejdys`
diff --git a/extensions/OrangeFactor/web/js/LICENSE.processing.js b/extensions/OrangeFactor/web/js/LICENSE.processing.js
new file mode 100644
index 000000000..404e5d5eb
--- /dev/null
+++ b/extensions/OrangeFactor/web/js/LICENSE.processing.js
@@ -0,0 +1,22 @@
+Copyright (C) 2008 John Resig
+Copyright (C) 2009-2011; see the AUTHORS file for authors and
+copyright holders.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/extensions/OrangeFactor/web/js/LICENSE.sparklines.js b/extensions/OrangeFactor/web/js/LICENSE.sparklines.js
new file mode 100644
index 000000000..73aaca832
--- /dev/null
+++ b/extensions/OrangeFactor/web/js/LICENSE.sparklines.js
@@ -0,0 +1,20 @@
+Copyright (C) 2008 Will Larson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/extensions/OrangeFactor/web/js/orange_factor.js b/extensions/OrangeFactor/web/js/orange_factor.js
new file mode 100644
index 000000000..da993580d
--- /dev/null
+++ b/extensions/OrangeFactor/web/js/orange_factor.js
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YAHOO.namespace('OrangeFactor');
+
+var OrangeFactor = YAHOO.OrangeFactor;
+
+OrangeFactor.dayMs = 24 * 60 * 60 * 1000,
+OrangeFactor.limit = 7;
+
+OrangeFactor.getOrangeCount = function (data) {
+ data = data.oranges;
+ var total = 0,
+ days = [],
+ date = OrangeFactor.getCurrentDateMs() - OrangeFactor.limit * OrangeFactor.dayMs;
+ for(var i = 0; i < OrangeFactor.limit; i++) {
+ var iso = OrangeFactor.dateString(new Date(date));
+ var count = data[iso] ? data[iso].orangecount : 0;
+ days.push(count);
+ total += count;
+ date += OrangeFactor.dayMs;
+ }
+ OrangeFactor.displayGraph(days);
+ OrangeFactor.displayCount(total);
+}
+
+OrangeFactor.displayGraph = function (dayCounts) {
+ var max = dayCounts.reduce(function(max, count) {
+ return count > max ? count : max;
+ });
+ var graphContainer = YAHOO.util.Dom.get('orange-graph');
+ Dom.removeClass(graphContainer, 'bz_default_hidden');
+ YAHOO.util.Dom.setAttribute(graphContainer, 'title',
+ 'failures over the past week, max in a day: ' + max);
+ var opts = {
+ "percentage_lines":[0.25, 0.5, 0.75],
+ "fill_between_percentage_lines": false,
+ "left_padding": 0,
+ "right_padding": 0,
+ "top_padding": 0,
+ "bottom_padding": 0,
+ "background": "#D0D0D0",
+ "stroke": "#000000",
+ "percentage_fill_color": "#CCCCFF",
+ "scale_from_zero": true,
+ };
+ new Sparkline('orange-graph', dayCounts, opts).draw();
+}
+
+OrangeFactor.displayCount = function (count) {
+ var countContainer = YAHOO.util.Dom.get('orange-count');
+ countContainer.innerHTML = encodeURIComponent(count) +
+ ' failures on trunk in the past week';
+}
+
+OrangeFactor.dateString = function (date) {
+ function norm(part) {
+ return JSON.stringify(part).length == 2 ? part : '0' + part;
+ }
+ return date.getFullYear()
+ + "-" + norm(date.getMonth() + 1)
+ + "-" + norm(date.getDate());
+}
+
+OrangeFactor.getCurrentDateMs = function () {
+ var d = new Date;
+ return d.getTime();
+}
+
+OrangeFactor.orangify = function () {
+ var bugId = document.forms['changeform'].id.value;
+ var url = "https://brasstacks.mozilla.com/orangefactor/api/count?" +
+ "bugid=" + encodeURIComponent(bugId) +
+ "&tree=trunk" +
+ "&callback=OrangeFactor.getOrangeCount";
+ var script = document.createElement('script');
+ Dom.setAttribute(script, 'src', url);
+ Dom.setAttribute(script, 'type', 'text/javascript');
+ var head = document.getElementsByTagName('head')[0];
+ head.appendChild(script);
+ var countContainer = YAHOO.util.Dom.get('orange-count');
+ Dom.removeClass(countContainer, 'bz_default_hidden');
+ countContainer.innerHTML = 'Loading...';a
+}
+
+YAHOO.util.Event.onDOMReady(OrangeFactor.orangify);
diff --git a/extensions/OrangeFactor/web/js/sparklines.min.js b/extensions/OrangeFactor/web/js/sparklines.min.js
new file mode 100644
index 000000000..f1043c55e
--- /dev/null
+++ b/extensions/OrangeFactor/web/js/sparklines.min.js
@@ -0,0 +1,133 @@
+/* Sparklines.js - Will Larson (http://lethain.com)
+ * This code is distributed under the MIT license.
+ * See LICENSE.sparklines.js
+ * More information: https://github.com/lethain/sparklines.js
+ *
+ * Processing.js - John Resig (http://ejohn.org/)
+ * See LICENSE.processing.js and AUTHORS.processing.js
+ * More information: http://processingjs.org/
+ */
+(function(){this.Processing=function Processing(aElement,aCode){if(typeof aElement=="string")
+aElement=document.getElementById(aElement);var p=buildProcessing(aElement);if(aCode)
+p.init(aCode);return p;};function log(){try{console.log.apply(console,arguments);}catch(e){try{opera.postError.apply(opera,arguments);}catch(e){}}}
+var parse=Processing.parse=function parse(aCode,p){aCode=aCode.replace(/\/\/ .*\n/g,"\n");aCode=aCode.replace(/([^\s])%([^\s])/g,"$1 % $2");aCode=aCode.replace(/(?:static )?(\w+ )(\w+)\s*(\([^\)]*\)\s*{)/g,function(all,type,name,args){if(name=="if"||name=="for"||name=="while"){return all;}else{return"Processing."+name+" = function "+name+args;}});aCode=aCode.replace(/\.length\(\)/g,".length");aCode=aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g,"$1$4");aCode=aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g,"$1$4");aCode=aCode.replace(/new (\w+)((?:\[([^\]]*)\])+)/g,function(all,name,args){return"new ArrayList("+args.slice(1,-1).split("][").join(", ")+")";});aCode=aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*{.*?};/g,function(all){return all.replace(/{/g,"[").replace(/}/g,"]");});var intFloat=/(\n\s*(?:int|float)(?:\[\])?(?:\s*|[^\(]*?,\s*))([a-z]\w*)(;|,)/i;while(intFloat.test(aCode)){aCode=aCode.replace(new RegExp(intFloat),function(all,type,name,sep){return type+" "+name+" = 0"+sep;});}
+aCode=aCode.replace(/(?:static )?(\w+)((?:\[\])+| ) *(\w+)\[?\]?(\s*[=,;])/g,function(all,type,arr,name,sep){if(type=="return")
+return all;else
+return"var "+name+sep;});aCode=aCode.replace(/=\s*{((.|\s)*?)};/g,function(all,data){return"= ["+data.replace(/{/g,"[").replace(/}/g,"]")+"]";});aCode=aCode.replace(/static\s*{((.|\n)*?)}/g,function(all,init){return init;});aCode=aCode.replace(/super\(/g,"superMethod(");var classes=["int","float","boolean","string"];function ClassReplace(all,name,extend,vars,last){classes.push(name);var static="";vars=vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g,function(all,set){static+=" "+name+"."+set;return"";});return"function "+name+"() {with(this){\n "+
+(extend?"var __self=this;function superMethod(){extendClass(__self,arguments,"+extend+");}\n":"")+
+vars.replace(/,\s?/g,";\n this.").replace(/\b(var |final |public )+\s*/g,"this.").replace(/this.(\w+);/g,"this.$1 = null;")+
+(extend?"extendClass(this, "+extend+");\n":"")+"<CLASS "+name+" "+static+">"+(typeof last=="string"?last:name+"(");}
+var matchClasses=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g;var matchNoCon=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g;aCode=aCode.replace(matchClasses,ClassReplace);aCode=aCode.replace(matchNoCon,ClassReplace);var matchClass=/<CLASS (\w+) (.*?)>/,m;while((m=aCode.match(matchClass))){var left=RegExp.leftContext,allRest=RegExp.rightContext,rest=nextBrace(allRest),className=m[1],staticVars=m[2]||"";allRest=allRest.slice(rest.length+1);rest=rest.replace(new RegExp("\\b"+className+"\\(([^\\)]*?)\\)\\s*{","g"),function(all,args){args=args.split(/,\s*?/);if(args[0].match(/^\s*$/))
+args.shift();var fn="if ( arguments.length == "+args.length+" ) {\n";for(var i=0;i<args.length;i++){fn+=" var "+args[i]+" = arguments["+i+"];\n";}
+return fn;});rest=rest.replace(/(?:public )?Processing.\w+ = function (\w+)\((.*?)\)/g,function(all,name,args){return"ADDMETHOD(this, '"+name+"', function("+args+")";});var matchMethod=/ADDMETHOD([\s\S]*?{)/,mc;var methods="";while((mc=rest.match(matchMethod))){var prev=RegExp.leftContext,allNext=RegExp.rightContext,next=nextBrace(allNext);methods+="addMethod"+mc[1]+next+"});"
+rest=prev+allNext.slice(next.length+1);}
+rest=methods+rest;aCode=left+rest+"\n}}"+staticVars+allRest;}
+aCode=aCode.replace(/Processing.\w+ = function addMethod/g,"addMethod");function nextBrace(right){var rest=right;var position=0;var leftCount=1,rightCount=0;while(leftCount!=rightCount){var nextLeft=rest.indexOf("{");var nextRight=rest.indexOf("}");if(nextLeft<nextRight&&nextLeft!=-1){leftCount++;rest=rest.slice(nextLeft+1);position+=nextLeft+1;}else{rightCount++;rest=rest.slice(nextRight+1);position+=nextRight+1;}}
+return right.slice(0,position-1);}
+aCode=aCode.replace(/\(int\)/g,"0|");aCode=aCode.replace(new RegExp("\\(("+classes.join("|")+")(\\[\\])?\\)","g"),"");aCode=aCode.replace(/(\d+)f/g,"$1");aCode=aCode.replace(/('[a-zA-Z0-9]')/g,"$1.charCodeAt(0)");aCode=aCode.replace(/#([a-f0-9]{6})/ig,function(m,hex){var num=toNumbers(hex);return"color("+num[0]+","+num[1]+","+num[2]+")";});function toNumbers(str){var ret=[];str.replace(/(..)/g,function(str){ret.push(parseInt(str,16));});return ret;}
+return aCode;};function buildProcessing(curElement){var p={};p.PI=Math.PI;p.TWO_PI=2*p.PI;p.HALF_PI=p.PI/2;p.P3D=3;p.CORNER=0;p.RADIUS=1;p.CENTER_RADIUS=1;p.CENTER=2;p.POLYGON=2;p.QUADS=5;p.TRIANGLES=6;p.POINTS=7;p.LINES=8;p.TRIANGLE_STRIP=9;p.TRIANGLE_FAN=4;p.QUAD_STRIP=3;p.CORNERS=10;p.CLOSE=true;p.RGB=1;p.HSB=2;p.LEFT=1;p.CENTER=2;p.RIGHT=3;var curContext=curElement.getContext("2d");var doFill=true;var doStroke=true;var loopStarted=false;var hasBackground=false;var doLoop=true;var looping=0;var curRectMode=p.CORNER;var curEllipseMode=p.CENTER;var inSetup=false;var inDraw=false;var curBackground="rgba(204,204,204,1)";var curFrameRate=1000;var curShape=p.POLYGON;var curShapeCount=0;var curvePoints=[];var curTightness=0;var opacityRange=255;var redRange=255;var greenRange=255;var blueRange=255;var pathOpen=false;var mousePressed=false;var keyPressed=false;var firstX,firstY,secondX,secondY,prevX,prevY;var curColorMode=p.RGB;var curTint=-1;var curTextSize=12;var curTextFont="Arial";var getLoaded=false;var start=(new Date).getTime();p.pmouseX=0;p.pmouseY=0;p.mouseX=0;p.mouseY=0;p.mouseButton=0;p.mouseDragged=undefined;p.mouseMoved=undefined;p.mousePressed=undefined;p.mouseReleased=undefined;p.keyPressed=undefined;p.keyReleased=undefined;p.draw=undefined;p.setup=undefined;p.width=curElement.width-0;p.height=curElement.height-0;p.frameCount=0;p.color=function color(aValue1,aValue2,aValue3,aValue4){var aColor="";if(arguments.length==3){aColor=p.color(aValue1,aValue2,aValue3,opacityRange);}else if(arguments.length==4){var a=aValue4/opacityRange;a=isNaN(a)?1:a;if(curColorMode==p.HSB){var rgb=HSBtoRGB(aValue1,aValue2,aValue3);var r=rgb[0],g=rgb[1],b=rgb[2];}else{var r=getColor(aValue1,redRange);var g=getColor(aValue2,greenRange);var b=getColor(aValue3,blueRange);}
+aColor="rgba("+r+","+g+","+b+","+a+")";}else if(typeof aValue1=="string"){aColor=aValue1;if(arguments.length==2){var c=aColor.split(",");c[3]=(aValue2/opacityRange)+")";aColor=c.join(",");}}else if(arguments.length==2){aColor=p.color(aValue1,aValue1,aValue1,aValue2);}else if(typeof aValue1=="number"){aColor=p.color(aValue1,aValue1,aValue1,opacityRange);}else{aColor=p.color(redRange,greenRange,blueRange,opacityRange);}
+function HSBtoRGB(h,s,b){h=(h/redRange)*100;s=(s/greenRange)*100;b=(b/blueRange)*100;if(s==0){return[b,b,b];}else{var hue=h%360;var f=hue%60;var br=Math.round(b/100*255);var p=Math.round((b*(100-s))/10000*255);var q=Math.round((b*(6000-s*f))/600000*255);var t=Math.round((b*(6000-s*(60-f)))/600000*255);switch(Math.floor(hue/60)){case 0:return[br,t,p];case 1:return[q,br,p];case 2:return[p,br,t];case 3:return[p,q,br];case 4:return[t,p,br];case 5:return[br,p,q];}}}
+function getColor(aValue,range){return Math.round(255*(aValue/range));}
+return aColor;}
+p.nf=function(num,pad){var str=""+num;while(pad-str.length)
+str="0"+str;return str;};p.AniSprite=function(prefix,frames){this.images=[];this.pos=0;for(var i=0;i<frames;i++){this.images.push(prefix+p.nf(i,(""+frames).length)+".gif");}
+this.display=function(x,y){p.image(this.images[this.pos],x,y);if(++this.pos>=frames)
+this.pos=0;};this.getWidth=function(){return getImage(this.images[0]).width;};this.getHeight=function(){return getImage(this.images[0]).height;};};function buildImageObject(obj){var pixels=obj.data;var data=p.createImage(obj.width,obj.height);if(data.__defineGetter__&&data.__lookupGetter__&&!data.__lookupGetter__("pixels")){var pixelsDone;data.__defineGetter__("pixels",function(){if(pixelsDone)
+return pixelsDone;pixelsDone=[];for(var i=0;i<pixels.length;i+=4){pixelsDone.push(p.color(pixels[i],pixels[i+1],pixels[i+2],pixels[i+3]));}
+return pixelsDone;});}else{data.pixels=[];for(var i=0;i<pixels.length;i+=4){data.pixels.push(p.color(pixels[i],pixels[i+1],pixels[i+2],pixels[i+3]));}}
+return data;}
+p.createImage=function createImage(w,h,mode){var data={};data.width=w;data.height=h;data.data=[];if(curContext.createImageData){data=curContext.createImageData(w,h);}
+data.pixels=new Array(w*h);data.get=function(x,y){return this.pixels[w*y+x];};data._mask=null;data.mask=function(img){this._mask=img;};data.loadPixels=function(){};data.updatePixels=function(){};return data;};p.createGraphics=function createGraphics(w,h){var canvas=document.createElement("canvas");var ret=buildProcessing(canvas);ret.size(w,h);ret.canvas=canvas;return ret;};p.beginDraw=function beginDraw(){};p.endDraw=function endDraw(){};p.tint=function tint(rgb,a){curTint=a;};function getImage(img){if(typeof img=="string"){return document.getElementById(img);}
+if(img.img||img.canvas){return img.img||img.canvas;}
+for(var i=0,l=img.pixels.length;i<l;i++){var pos=i*4;var c=(img.pixels[i]||"rgba(0,0,0,1)").slice(5,-1).split(",");img.data[pos]=parseInt(c[0]);img.data[pos+1]=parseInt(c[1]);img.data[pos+2]=parseInt(c[2]);img.data[pos+3]=parseFloat(c[3])*100;}
+var canvas=document.createElement("canvas")
+canvas.width=img.width;canvas.height=img.height;var context=canvas.getContext("2d");context.putImageData(img,0,0);img.canvas=canvas;return canvas;}
+p.image=function image(img,x,y,w,h){x=x||0;y=y||0;var obj=getImage(img);if(curTint>=0){var oldAlpha=curContext.globalAlpha;curContext.globalAlpha=curTint/opacityRange;}
+if(arguments.length==3){curContext.drawImage(obj,x,y);}else{curContext.drawImage(obj,x,y,w,h);}
+if(curTint>=0){curContext.globalAlpha=oldAlpha;}
+if(img._mask){var oldComposite=curContext.globalCompositeOperation;curContext.globalCompositeOperation="darker";p.image(img._mask,x,y);curContext.globalCompositeOperation=oldComposite;}};p.exit=function exit(){clearInterval(looping);};p.save=function save(file){};p.loadImage=function loadImage(file){var img=document.getElementById(file);if(!img)
+return;var h=img.height,w=img.width;var canvas=document.createElement("canvas");canvas.width=w;canvas.height=h;var context=canvas.getContext("2d");context.drawImage(img,0,0);var data=buildImageObject(context.getImageData(0,0,w,h));data.img=img;return data;};p.loadFont=function loadFont(name){return{name:name,width:function(str){if(curContext.mozMeasureText)
+return curContext.mozMeasureText(typeof str=="number"?String.fromCharCode(str):str)/curTextSize;else
+return 0;}};};p.textFont=function textFont(name,size){curTextFont=name;p.textSize(size);};p.textSize=function textSize(size){if(size){curTextSize=size;}};p.textAlign=function textAlign(){};p.text=function text(str,x,y){if(str&&curContext.mozDrawText){curContext.save();curContext.mozTextStyle=curTextSize+"px "+curTextFont.name;curContext.translate(x,y);curContext.mozDrawText(typeof str=="number"?String.fromCharCode(str):str);curContext.restore();}};p.char=function char(key){return key;};p.println=function println(){};p.map=function map(value,istart,istop,ostart,ostop){return ostart+(ostop-ostart)*((value-istart)/(istop-istart));};String.prototype.replaceAll=function(re,replace){return this.replace(new RegExp(re,"g"),replace);};p.Point=function Point(x,y){this.x=x;this.y=y;this.copy=function(){return new Point(x,y);}};p.Random=function(){var haveNextNextGaussian=false;var nextNextGaussian;this.nextGaussian=function(){if(haveNextNextGaussian){haveNextNextGaussian=false;return nextNextGaussian;}else{var v1,v2,s;do{v1=2*p.random(1)-1;v2=2*p.random(1)-1;s=v1*v1+v2*v2;}while(s>=1||s==0);var multiplier=Math.sqrt(-2*Math.log(s)/s);nextNextGaussian=v2*multiplier;haveNextNextGaussian=true;return v1*multiplier;}};};p.ArrayList=function ArrayList(size,size2,size3){var array=new Array(0|size);if(size2){for(var i=0;i<size;i++){array[i]=[];for(var j=0;j<size2;j++){var a=array[i][j]=size3?new Array(size3):0;for(var k=0;k<size3;k++){a[k]=0;}}}}else{for(var i=0;i<size;i++){array[i]=0;}}
+array.size=function(){return this.length;};array.get=function(i){return this[i];};array.remove=function(i){return this.splice(i,1);};array.add=function(item){return this.push(item);};array.clone=function(){var a=new ArrayList(size);for(var i=0;i<size;i++){a[i]=this[i];}
+return a;};array.isEmpty=function(){return!this.length;};array.clear=function(){this.length=0;};return array;};p.colorMode=function colorMode(mode,range1,range2,range3,range4){curColorMode=mode;if(arguments.length>=4){redRange=range1;greenRange=range2;blueRange=range3;}
+if(arguments.length==5){opacityRange=range4;}
+if(arguments.length==2){p.colorMode(mode,range1,range1,range1,range1);}};p.beginShape=function beginShape(type){curShape=type;curShapeCount=0;curvePoints=[];};p.endShape=function endShape(close){if(curShapeCount!=0){if(close||doFill)
+curContext.lineTo(firstX,firstY);if(doFill)
+curContext.fill();if(doStroke)
+curContext.stroke();curContext.closePath();curShapeCount=0;pathOpen=false;}
+if(pathOpen){if(doFill)
+curContext.fill();if(doStroke)
+curContext.stroke();curContext.closePath();curShapeCount=0;pathOpen=false;}};p.vertex=function vertex(x,y,x2,y2,x3,y3){if(curShapeCount==0&&curShape!=p.POINTS){pathOpen=true;curContext.beginPath();curContext.moveTo(x,y);firstX=x;firstY=y;}else{if(curShape==p.POINTS){p.point(x,y);}else if(arguments.length==2){if(curShape!=p.QUAD_STRIP||curShapeCount!=2)
+curContext.lineTo(x,y);if(curShape==p.TRIANGLE_STRIP){if(curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;}
+firstX=prevX;firstY=prevY;}
+if(curShape==p.TRIANGLE_FAN&&curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(firstX,firstY);curContext.lineTo(x,y);curShapeCount=1;}
+if(curShape==p.QUAD_STRIP&&curShapeCount==3){curContext.lineTo(prevX,prevY);p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;}
+if(curShape==p.QUAD_STRIP){firstX=secondX;firstY=secondY;secondX=prevX;secondY=prevY;}}else if(arguments.length==4){if(curShapeCount>1){curContext.moveTo(prevX,prevY);curContext.quadraticCurveTo(firstX,firstY,x,y);curShapeCount=1;}}else if(arguments.length==6){curContext.bezierCurveTo(x,y,x2,y2,x3,y3);curShapeCount=-1;}}
+prevX=x;prevY=y;curShapeCount++;if(curShape==p.LINES&&curShapeCount==2||(curShape==p.TRIANGLES)&&curShapeCount==3||(curShape==p.QUADS)&&curShapeCount==4){p.endShape(p.CLOSE);}};p.curveVertex=function(x,y,x2,y2){if(curvePoints.length<3){curvePoints.push([x,y]);}else{var b=[],s=1-curTightness;curvePoints.push([x,y]);b[0]=[curvePoints[1][0],curvePoints[1][1]];b[1]=[curvePoints[1][0]+(s*curvePoints[2][0]-s*curvePoints[0][0])/6,curvePoints[1][1]+(s*curvePoints[2][1]-s*curvePoints[0][1])/6];b[2]=[curvePoints[2][0]+(s*curvePoints[1][0]-s*curvePoints[3][0])/6,curvePoints[2][1]+(s*curvePoints[1][1]-s*curvePoints[3][1])/6];b[3]=[curvePoints[2][0],curvePoints[2][1]];if(!pathOpen){p.vertex(b[0][0],b[0][1]);}else{curShapeCount=1;}
+p.vertex(b[1][0],b[1][1],b[2][0],b[2][1],b[3][0],b[3][1]);curvePoints.shift();}};p.curveTightness=function(tightness){curTightness=tightness;};p.bezierVertex=p.vertex;p.rectMode=function rectMode(aRectMode){curRectMode=aRectMode;};p.imageMode=function(){};p.ellipseMode=function ellipseMode(aEllipseMode){curEllipseMode=aEllipseMode;};p.dist=function dist(x1,y1,x2,y2){return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));};p.year=function year(){return(new Date).getYear()+1900;};p.month=function month(){return(new Date).getMonth();};p.day=function day(){return(new Date).getDay();};p.hour=function hour(){return(new Date).getHours();};p.minute=function minute(){return(new Date).getMinutes();};p.second=function second(){return(new Date).getSeconds();};p.millis=function millis(){return(new Date).getTime()-start;};p.ortho=function ortho(){};p.translate=function translate(x,y){curContext.translate(x,y);};p.scale=function scale(x,y){curContext.scale(x,y||x);};p.rotate=function rotate(aAngle){curContext.rotate(aAngle);};p.pushMatrix=function pushMatrix(){curContext.save();};p.popMatrix=function popMatrix(){curContext.restore();};p.redraw=function redraw(){if(hasBackground){p.background();}
+p.frameCount++;inDraw=true;p.pushMatrix();p.draw();p.popMatrix();inDraw=false;};p.loop=function loop(){if(loopStarted)
+return;looping=setInterval(function(){try{p.redraw();}
+catch(e){clearInterval(looping);throw e;}},1000/curFrameRate);loopStarted=true;};p.frameRate=function frameRate(aRate){curFrameRate=aRate;};p.background=function background(img){if(arguments.length){if(img&&img.img){curBackground=img;}else{curBackground=p.color.apply(this,arguments);}}
+if(curBackground.img){p.image(curBackground,0,0);}else{var oldFill=curContext.fillStyle;curContext.fillStyle=curBackground+"";curContext.fillRect(0,0,p.width,p.height);curContext.fillStyle=oldFill;}};p.sq=function sq(aNumber){return aNumber*aNumber;};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.int=function int(aNumber){return Math.floor(aNumber);};p.min=function min(aNumber,aNumber2){return Math.min(aNumber,aNumber2);};p.max=function max(aNumber,aNumber2){return Math.max(aNumber,aNumber2);};p.ceil=function ceil(aNumber){return Math.ceil(aNumber);};p.floor=function floor(aNumber){return Math.floor(aNumber);};p.float=function float(aNumber){return typeof aNumber=="string"?p.float(aNumber.charCodeAt(0)):parseFloat(aNumber);};p.byte=function byte(aNumber){return aNumber||0;};p.random=function random(aMin,aMax){return arguments.length==2?aMin+(Math.random()*(aMax-aMin)):Math.random()*aMin;};p.noise=function(x,y,z){return arguments.length>=2?PerlinNoise_2D(x,y):PerlinNoise_2D(x,x);};function Noise(x,y){var n=x+y*57;n=(n<<13)^n;return Math.abs(1.0-(((n*((n*n*15731)+789221)+1376312589)&0x7fffffff)/1073741824.0));};function SmoothedNoise(x,y){var corners=(Noise(x-1,y-1)+Noise(x+1,y-1)+Noise(x-1,y+1)+Noise(x+1,y+1))/16;var sides=(Noise(x-1,y)+Noise(x+1,y)+Noise(x,y-1)+Noise(x,y+1))/8;var center=Noise(x,y)/4;return corners+sides+center;};function InterpolatedNoise(x,y){var integer_X=Math.floor(x);var fractional_X=x-integer_X;var integer_Y=Math.floor(y);var fractional_Y=y-integer_Y;var v1=SmoothedNoise(integer_X,integer_Y);var v2=SmoothedNoise(integer_X+1,integer_Y);var v3=SmoothedNoise(integer_X,integer_Y+1);var v4=SmoothedNoise(integer_X+1,integer_Y+1);var i1=Interpolate(v1,v2,fractional_X);var i2=Interpolate(v3,v4,fractional_X);return Interpolate(i1,i2,fractional_Y);}
+function PerlinNoise_2D(x,y){var total=0;var p=0.25;var n=3;for(var i=0;i<=n;i++){var frequency=Math.pow(2,i);var amplitude=Math.pow(p,i);total=total+InterpolatedNoise(x*frequency,y*frequency)*amplitude;}
+return total;}
+function Interpolate(a,b,x){var ft=x*p.PI;var f=(1-p.cos(ft))*.5;return a*(1-f)+b*f;}
+p.red=function(aColor){return parseInt(aColor.slice(5));};p.green=function(aColor){return parseInt(aColor.split(",")[1]);};p.blue=function(aColor){return parseInt(aColor.split(",")[2]);};p.alpha=function(aColor){return parseInt(aColor.split(",")[3]);};p.abs=function abs(aNumber){return Math.abs(aNumber);};p.cos=function cos(aNumber){return Math.cos(aNumber);};p.sin=function sin(aNumber){return Math.sin(aNumber);};p.pow=function pow(aNumber,aExponent){return Math.pow(aNumber,aExponent);};p.constrain=function constrain(aNumber,aMin,aMax){return Math.min(Math.max(aNumber,aMin),aMax);};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.atan2=function atan2(aNumber,aNumber2){return Math.atan2(aNumber,aNumber2);};p.radians=function radians(aAngle){return(aAngle/180)*p.PI;};p.size=function size(aWidth,aHeight){var fillStyle=curContext.fillStyle;var strokeStyle=curContext.strokeStyle;curElement.width=p.width=aWidth;curElement.height=p.height=aHeight;curContext.fillStyle=fillStyle;curContext.strokeStyle=strokeStyle;};p.noStroke=function noStroke(){doStroke=false;};p.noFill=function noFill(){doFill=false;};p.smooth=function smooth(){};p.noLoop=function noLoop(){doLoop=false;};p.fill=function fill(){doFill=true;curContext.fillStyle=p.color.apply(this,arguments);};p.stroke=function stroke(){doStroke=true;curContext.strokeStyle=p.color.apply(this,arguments);};p.strokeWeight=function strokeWeight(w){curContext.lineWidth=w;};p.point=function point(x,y){var oldFill=curContext.fillStyle;curContext.fillStyle=curContext.strokeStyle;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;};p.get=function get(x,y){if(arguments.length==0){var c=p.createGraphics(p.width,p.height);c.image(curContext,0,0);return c;}
+if(!getLoaded){getLoaded=buildImageObject(curContext.getImageData(0,0,p.width,p.height));}
+return getLoaded.get(x,y);};p.set=function set(x,y,obj){if(obj&&obj.img){p.image(obj,x,y);}else{var oldFill=curContext.fillStyle;var color=obj;curContext.fillStyle=color;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;}};p.arc=function arc(x,y,width,height,start,stop){if(width<=0)
+return;if(curEllipseMode==p.CORNER){x+=width/2;y+=height/2;}
+curContext.beginPath();curContext.moveTo(x,y);curContext.arc(x,y,curEllipseMode==p.CENTER_RADIUS?width:width/2,start,stop,false);if(doFill)
+curContext.fill();if(doStroke)
+curContext.stroke();curContext.closePath();};p.line=function line(x1,y1,x2,y2){curContext.lineCap="round";curContext.beginPath();curContext.moveTo(x1||0,y1||0);curContext.lineTo(x2||0,y2||0);curContext.stroke();curContext.closePath();};p.bezier=function bezier(x1,y1,x2,y2,x3,y3,x4,y4){curContext.lineCap="butt";curContext.beginPath();curContext.moveTo(x1,y1);curContext.bezierCurveTo(x2,y2,x3,y3,x4,y4);curContext.stroke();curContext.closePath();};p.triangle=function triangle(x1,y1,x2,y2,x3,y3){p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.endShape();};p.quad=function quad(x1,y1,x2,y2,x3,y3,x4,y4){p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.vertex(x4,y4);p.endShape();};p.rect=function rect(x,y,width,height){if(width==0&&height==0)
+return;curContext.beginPath();var offsetStart=0;var offsetEnd=0;if(curRectMode==p.CORNERS){width-=x;height-=y;}
+if(curRectMode==p.RADIUS){width*=2;height*=2;}
+if(curRectMode==p.CENTER||curRectMode==p.RADIUS){x-=width/2;y-=height/2;}
+curContext.rect(Math.round(x)-offsetStart,Math.round(y)-offsetStart,Math.round(width)+offsetEnd,Math.round(height)+offsetEnd);if(doFill)
+curContext.fill();if(doStroke)
+curContext.stroke();curContext.closePath();};p.ellipse=function ellipse(x,y,width,height){x=x||0;y=y||0;if(width<=0&&height<=0)
+return;curContext.beginPath();if(curEllipseMode==p.RADIUS){width*=2;height*=2;}
+var offsetStart=0;if(width==height)
+curContext.arc(x-offsetStart,y-offsetStart,width/2,0,Math.PI*2,false);if(doFill)
+curContext.fill();if(doStroke)
+curContext.stroke();curContext.closePath();};p.link=function(href,target){window.location=href;};p.loadPixels=function(){p.pixels=buildImageObject(curContext.getImageData(0,0,p.width,p.height)).pixels;};p.updatePixels=function(){var colors=/(\d+),(\d+),(\d+),(\d+)/;var pixels={};pixels.width=p.width;pixels.height=p.height;pixels.data=[];if(curContext.createImageData){pixels=curContext.createImageData(p.width,p.height);}
+var data=pixels.data;var pos=0;for(var i=0,l=p.pixels.length;i<l;i++){var c=(p.pixels[i]||"rgba(0,0,0,1)").match(colors);data[pos]=parseInt(c[1]);data[pos+1]=parseInt(c[2]);data[pos+2]=parseInt(c[3]);data[pos+3]=parseFloat(c[4])*100;pos+=4;}
+curContext.putImageData(pixels,0,0);};p.extendClass=function extendClass(obj,args,fn){if(arguments.length==3){fn.apply(obj,args);}else{args.call(obj);}};p.addMethod=function addMethod(object,name,fn){if(object[name]){var args=fn.length;var oldfn=object[name];object[name]=function(){if(arguments.length==args)
+return fn.apply(this,arguments);else
+return oldfn.apply(this,arguments);};}else{object[name]=fn;}};p.init=function init(code){p.stroke(0);p.fill(255);curContext.translate(0.5,0.5);if(code){(function(Processing){with(p){eval(parse(code,p));}})(p);}
+if(p.setup){inSetup=true;p.setup();}
+inSetup=false;if(p.draw){if(!doLoop){p.redraw();}else{p.loop();}}
+attach(curElement,"mousemove",function(e){var scrollX=window.scrollX!=null?window.scrollX:window.pageXOffset;var scrollY=window.scrollY!=null?window.scrollY:window.pageYOffset;p.pmouseX=p.mouseX;p.pmouseY=p.mouseY;p.mouseX=e.clientX-curElement.offsetLeft+scrollX;p.mouseY=e.clientY-curElement.offsetTop+scrollY;if(p.mouseMoved){p.mouseMoved();}
+if(mousePressed&&p.mouseDragged){p.mouseDragged();}});attach(curElement,"mousedown",function(e){mousePressed=true;p.mouseButton=e.which;if(typeof p.mousePressed=="function"){p.mousePressed();}else{p.mousePressed=true;}});attach(curElement,"contextmenu",function(e){e.preventDefault();e.stopPropagation();});attach(curElement,"mouseup",function(e){mousePressed=false;if(typeof p.mousePressed!="function"){p.mousePressed=false;}
+if(p.mouseReleased){p.mouseReleased();}});attach(document,"keydown",function(e){keyPressed=true;p.key=e.keyCode+32;if(e.shiftKey){p.key=String.fromCharCode(p.key).toUpperCase().charCodeAt(0);}
+if(typeof p.keyPressed=="function"){p.keyPressed();}else{p.keyPressed=true;}});attach(document,"keyup",function(e){keyPressed=false;if(typeof p.keyPressed!="function"){p.keyPressed=false;}
+if(p.keyReleased){p.keyReleased();}});function attach(elem,type,fn){if(elem.addEventListener)
+elem.addEventListener(type,fn,false);else
+elem.attachEvent("on"+type,fn);}};return p;}})();if(!Array.prototype.map)
+{Array.prototype.map=function(fun)
+{var len=this.length;if(typeof fun!="function")
+throw new TypeError();var res=new Array(len);var thisp=arguments[1];for(var i=0;i<len;i++)
+{if(i in this)
+res[i]=fun.call(thisp,this[i],i,this);}
+return res;};}
+var BaseSparkline=function(){this.init=function(id,data,mixins){this.background=50;this.stroke="rgba(230,230,230,0.70);";this.percentage_color="#5555FF";this.percentage_fill_color=75;this.value_line_color="#7777FF";this.value_line_fill_color=85;this.canvas=document.getElementById(id);this.data=data;this.scale_from=undefined;this.scale_to=undefined;this.top_padding=10;this.bottom_padding=10;this.left_padding=10;this.right_padding=10;this.percentage_lines=[];this.fill_between_percentage_lines=false;this.value_lines=[];this.fill_between_value_lines=false;for(var property in mixins)this[property]=mixins[property];};this.parse_height=function(x){return x;};this.heights=function(){return this.data.map(this.parse_height);};this.max=function(){var vals=this.heights();var max=vals[0];var l=vals.length;for(var i=1;i<l;i++)max=Math.max(max,vals[i]);return max;};this.min=function(){var vals=this.heights();var min=vals[0];var l=vals.length;for(var i=1;i<l;i++)min=Math.min(min,vals[i]);return min;};this.height=function(){return this.canvas.height-this.top_padding-this.bottom_padding;};this.width=function(){return this.canvas.width-this.left_padding-this.right_padding;};this.scale_values=function(values,max){if(!max)max=this.max();var p=this.top_padding;var h=this.height();var top=(this.scale_to!=undefined)?this.scale_to:max;var bottom=(this.scale_from!=undefined)?this.scale_from:this.min();var range=Math.abs(top-bottom);var scale=function(x){var percentage=((x-bottom)*1.0)/range;return h-(h*percentage)+p;};return values.map(scale,this);};this.calc_value_lines=function(){var scaled=this.scale_values(this.value_lines);scaled.sort(function(a,b){return a-b;});return scaled;};this.calc_percentages=function(){var sorted=this.heights();sorted.sort(function(a,b){return a-b;});var points=[];var n=sorted.length;var l=this.percentage_lines.length;for(var i=0;i<l;i++){var percentage=this.percentage_lines[i];var position=Math.round(percentage*(n+1));points.push(sorted[position]);}
+var max=sorted[n-1];var raws=this.scale_values(points,max);raws.sort(function(a,b){return a-b;});return raws;};this.scale_height=function(){return this.scale_values(this.heights());};this.segment_width=function(){var w=this.width();var l=this.data.length;return(w*1.0)/(l-1);};this.scale_width=function(){var widths=[];var l=this.data.length;var segment_width=this.segment_width();for(var i=0;i<l;i++){widths.push((i*segment_width)+this.left_padding);}
+return widths;};this.scale_data=function(){var heights=this.scale_height();var widths=this.scale_width();var l=heights.length;var data=[];for(var i=0;i<l;i++)
+data.push({'y':heights[i],'x':widths[i]});return data;};this.draw=function(){var sl=this;with(Processing(sl.canvas)){setup=function(){};draw=function(){background(sl.background);scaled=sl.scale_data();var l=scaled.length;var percentages=sl.calc_percentages();if(sl.fill_between_percentage_lines&&percentages.length>1){noStroke();fill(sl.percentage_fill_color);var height=percentages[percentages.length-1]-percentages[0];var width=scaled[l-1].x-scaled[0].x;rect(scaled[0].x,percentages[0],width,height);}
+var value_lines=sl.calc_value_lines();if(sl.fill_between_value_lines&&value_lines.length>1){noStroke();fill(sl.value_line_fill_color);var height=value_lines[value_lines.length-1]-value_lines[0];var width=scaled[l-1].x-scaled[0].x;rect(scaled[0].x,value_lines[0],width,height);}
+stroke(sl.value_line_color);for(var h=0;h<value_lines.length;h++){var y=value_lines[h];line(scaled[0].x,y,scaled[l-1].x,y);}
+stroke(sl.percentage_color);for(var j=0;j<percentages.length;j++){var y=percentages[j];line(scaled[0].x,y,scaled[l-1].x,y);}
+stroke(sl.stroke);for(var i=1;i<l;i++){var curr=scaled[i];var previous=scaled[i-1];line(previous.x,previous.y,curr.x,curr.y);}
+this.exit();};init();};};};var Sparkline=function(id,data,mixins){this.init(id,data,mixins);}
+Sparkline.prototype=new BaseSparkline();var BarSparkline=function(id,data,mixins){if(!mixins)mixins={};this.marking_padding=5;this.padding_between_bars=5;this.extend_markings=true;if(!mixins.hasOwnProperty('scale_from'))mixins.scale_from=0;this.init(id,data,mixins);this.segment_width=function(){var l=this.data.length;var w=this.width();return((w*1.0)-((l-1)*this.padding_between_bars))/l;};this.scale_width=function(){var widths=[];var l=this.data.length;var segment_width=this.segment_width();for(var i=0;i<l;i++){widths.push((i*segment_width)+(this.padding_between_bars*i)+this.left_padding);}
+return widths;};this.draw=function(){var sl=this;with(Processing(sl.canvas)){draw=function(){background(sl.background);var scaled=sl.scale_data();var l=scaled.length;var sw=sl.segment_width();var gap=sl.padding_between_bars;var mp=sl.marking_padding;var value_lines=sl.calc_value_lines();if(sl.fill_between_value_lines&&value_lines.length>1){noStroke();fill(sl.percentage_fill_color);var height=value_lines[value_lines.length-1]-value_lines[0];var width=scaled[l-1].x-scaled[0].x+sw;if(sl.extend_markings){width+=2*mp;rect(scaled[0].x-mp,value_lines[0],width,height);}
+else rect(scaled[0].x,value_lines[0],width,height);}
+stroke(sl.value_line_color);for(var h=0;h<value_lines.length;h++){var y=value_lines[h];if(sl.extend_markings){line(scaled[0].x-mp,y,scaled[l-1].x+mp+sw,y);}
+else line(scaled[0].x,y,scaled[l-1].x+sw,y);}
+var percentages=sl.calc_percentages();if(sl.fill_between_percentage_lines&&percentages.length>1){noStroke();fill(sl.percentage_fill_color);var height=percentages[percentages.length-1]-percentages[0];var width=scaled[l-1].x-scaled[0].x+sw;if(sl.extend_markings){width+=2*mp;rect(scaled[0].x-mp,percentages[0],width,height);}
+else rect(scaled[0].x,percentages[0],width,height);}
+stroke(sl.percentage_color);for(var j=0;j<percentages.length;j++){var y=percentages[j];if(sl.extend_markings){line(scaled[0].x-mp,y,scaled[l-1].x+mp+sw,y);}
+else line(scaled[0].x,y,scaled[l-1].x+sw,y);}
+stroke(sl.stroke);fill(sl.stroke);var width=sl.segment_width();var height=sl.height();for(var i=0;i<l;i++){var d=scaled[i];rect(d.x,d.y,width,height-d.y);};this.exit();};init();};};}
+BarSparkline.prototype=new BaseSparkline();
diff --git a/extensions/OrangeFactor/web/style/orangefactor.css b/extensions/OrangeFactor/web/style/orangefactor.css
new file mode 100644
index 000000000..211ad575e
--- /dev/null
+++ b/extensions/OrangeFactor/web/style/orangefactor.css
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#orange-graph {
+ display: block;
+ width: 180px;
+ height: 38px;
+ margin: 0 .5em .5em 0;
+}
diff --git a/extensions/Persona/Config.pm b/extensions/Persona/Config.pm
new file mode 100644
index 000000000..8709655d1
--- /dev/null
+++ b/extensions/Persona/Config.pm
@@ -0,0 +1,29 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Persona;
+use strict;
+
+use constant NAME => 'Persona';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'JSON',
+ module => 'JSON',
+ version => 0,
+ },
+ {
+ package => 'libwww-perl',
+ module => 'LWP::UserAgent',
+ version => 0,
+ },
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/Persona/Extension.pm b/extensions/Persona/Extension.pm
new file mode 100644
index 000000000..f288702e8
--- /dev/null
+++ b/extensions/Persona/Extension.pm
@@ -0,0 +1,73 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Persona;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Config qw(SetParam write_params);
+
+our $VERSION = '0.01';
+
+sub install_update_db {
+ # The extension changed from BrowserID to Persona
+ # so we need to update user_info_class if this system
+ # was using BrowserID for verification.
+ my $params = Bugzilla->params || Bugzilla::Config::read_param_file();
+ my $user_info_class = $params->{'user_info_class'};
+ if ($user_info_class =~ /BrowserID/) {
+ $user_info_class =~ s/BrowserID/Persona/;
+ SetParam('user_info_class', $user_info_class);
+ write_params();
+ }
+}
+
+sub auth_login_methods {
+ my ($self, $args) = @_;
+ my $modules = $args->{'modules'};
+ if (exists($modules->{'Persona'})) {
+ $modules->{'Persona'} = 'Bugzilla/Extension/Persona/Login.pm';
+ }
+}
+
+sub config_modify_panels {
+ my ($self, $args) = @_;
+ my $panels = $args->{'panels'};
+ my $auth_panel_params = $panels->{'auth'}->{'params'};
+
+ my ($user_info_class) =
+ grep { $_->{'name'} eq 'user_info_class' } @$auth_panel_params;
+
+ if ($user_info_class) {
+ push(@{ $user_info_class->{'choices'} }, "Persona,CGI");
+ }
+
+ # The extension changed from BrowserID to Persona
+ # so we need to retain the current values for the new
+ # params that will be created.
+ my $params = Bugzilla->params || Bugzilla::Config::read_param_file();
+ my $verify_url = $params->{'browserid_verify_url'};
+ my $includejs_url = $params->{'browserid_includejs_url'};
+ if ($verify_url && $includejs_url) {
+ foreach my $param (@{ $panels->{'persona'}->{'params'} }) {
+ if ($param->{'name'} eq 'persona_verify_url') {
+ $param->{'default'} = $verify_url;
+ }
+ if ($param->{'name'} eq 'persona_includejs_url') {
+ $param->{'default'} = $includejs_url;
+ }
+ }
+ }
+}
+
+sub config_add_panels {
+ my ($self, $args) = @_;
+ my $modules = $args->{panel_modules};
+ $modules->{Persona} = "Bugzilla::Extension::Persona::Config";
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Persona/TODO b/extensions/Persona/TODO
new file mode 100644
index 000000000..ac94a3c42
--- /dev/null
+++ b/extensions/Persona/TODO
@@ -0,0 +1,19 @@
+ToDo:
+
+* Cache the LWP::UserAgent in Login.pm?
+
+* Fix Bugzilla::Auth::Login::Stack to allow failure part way down the chain
+ (currently, it seems that both CGI and BrowserID have to be last in order
+ to report login failures correctly.)
+
+* JS inclusions noticeably slow page load. Do we want a local copy of
+ browserid.js? Do the browserid folks object to that? How can we get good
+ performance? How can we avoid including it in every logged-in page? Can we
+ do demand loading onclick, and/or load-on-reveal?
+
+* Fix -8px margin-bottom hack in login-small-additional_methods.html.tmpl
+
+
+
+
+
diff --git a/extensions/Persona/lib/Config.pm b/extensions/Persona/lib/Config.pm
new file mode 100644
index 000000000..99c547b16
--- /dev/null
+++ b/extensions/Persona/lib/Config.pm
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Persona::Config;
+
+use strict;
+use warnings;
+
+use Bugzilla::Config::Common;
+
+our $sortkey = 1350;
+
+sub get_param_list {
+ my ($class) = @_;
+
+ my @param_list = (
+ {
+ name => 'persona_verify_url',
+ type => 't',
+ default => 'https://verifier.login.persona.org/verify',
+ },
+ {
+ name => 'persona_includejs_url',
+ type => 't',
+ default => 'https://login.persona.org/include.js',
+ }
+ );
+
+ return @param_list;
+}
+
+1;
diff --git a/extensions/Persona/lib/Login.pm b/extensions/Persona/lib/Login.pm
new file mode 100644
index 000000000..62fca4d50
--- /dev/null
+++ b/extensions/Persona/lib/Login.pm
@@ -0,0 +1,124 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Persona::Login;
+use strict;
+use base qw(Bugzilla::Auth::Login);
+
+use Bugzilla::Constants;
+use Bugzilla::Util;
+use Bugzilla::Error;
+use Bugzilla::Token;
+
+use JSON;
+use LWP::UserAgent;
+
+use constant requires_verification => 0;
+use constant is_automatic => 1;
+use constant user_can_create_account => 1;
+
+sub get_login_info {
+ my ($self) = @_;
+
+ my $cgi = Bugzilla->cgi;
+
+ my $assertion = $cgi->param("persona_assertion");
+ # Avoid the assertion being copied into any 'echoes' of the current URL
+ # in the page.
+ $cgi->delete('persona_assertion');
+
+ if (!$assertion || !Bugzilla->params->{persona_verify_url}) {
+ return { failure => AUTH_NODATA };
+ }
+
+ my $token = $cgi->param("token");
+ $cgi->delete('token');
+ check_hash_token($token, ['login']);
+
+ my $urlbase = new URI(correct_urlbase());
+ my $audience = $urlbase->scheme . "://" . $urlbase->host_port;
+
+ my $ua = new LWP::UserAgent( timeout => 10 );
+
+ my $response = $ua->post(Bugzilla->params->{persona_verify_url},
+ [ assertion => $assertion,
+ audience => $audience ]);
+ if ($response->is_error) {
+ return { failure => AUTH_ERROR,
+ user_error => 'persona_server_fail',
+ details => { reason => $response->message }};
+ }
+
+ my $info;
+ eval {
+ $info = decode_json($response->decoded_content());
+ };
+ if ($@) {
+ return { failure => AUTH_ERROR,
+ user_error => 'persona_server_fail',
+ details => { reason => 'Received a malformed response.' }};
+ }
+ if ($info->{'status'} eq 'failure') {
+ return { failure => AUTH_ERROR,
+ user_error => 'persona_server_fail',
+ details => { reason => $info->{reason} }};
+ }
+
+ if ($info->{'status'} eq "okay" &&
+ $info->{'audience'} eq $audience &&
+ ($info->{'expires'} / 1000) > time())
+ {
+ my $login_data = {
+ 'username' => $info->{'email'}
+ };
+
+ my $result = Bugzilla::Auth::Verify->create_or_update_user($login_data);
+ return $result if $result->{'failure'};
+
+ my $user = $result->{'user'};
+
+ # You can restrict people in a particular group from logging in using
+ # Persona by making that group a member of a group called
+ # "no-browser-id".
+ #
+ # If you have your "createemailregexp" set up in such a way that a
+ # newly-created account is a member of "no-browser-id", this code will
+ # create an account for them and then fail their login. Which isn't
+ # great, but they can still use normal-Bugzilla-login password
+ # recovery.
+ if ($user->in_group('no-browser-id')) {
+ return { failure => AUTH_ERROR,
+ user_error => 'persona_account_too_powerful' };
+ }
+
+ $login_data->{'user'} = $user;
+ $login_data->{'user_id'} = $user->id;
+
+ return $login_data;
+ }
+ else {
+ return { failure => AUTH_LOGINFAILED };
+ }
+}
+
+# Pinched from Bugzilla::Auth::Login::CGI
+sub fail_nodata {
+ my ($self) = @_;
+ my $cgi = Bugzilla->cgi;
+ my $template = Bugzilla->template;
+
+ if (Bugzilla->usage_mode != USAGE_MODE_BROWSER) {
+ ThrowUserError('login_required');
+ }
+
+ print $cgi->header();
+ $template->process("account/auth/login.html.tmpl", { 'target' => $cgi->url(-relative=>1) })
+ || ThrowTemplateError($template->error());
+ exit;
+}
+
+1;
diff --git a/extensions/Persona/template/en/default/admin/params/browserid.html.tmpl b/extensions/Persona/template/en/default/admin/params/browserid.html.tmpl
new file mode 100644
index 000000000..379d12058
--- /dev/null
+++ b/extensions/Persona/template/en/default/admin/params/browserid.html.tmpl
@@ -0,0 +1,22 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ title = "Persona"
+ desc = "Configure Persona Authentication"
+%]
+
+[% param_descs = {
+ persona_verify_url => "This is the URL for the Persona authority that the " _
+ "user will be verified against. " _
+ "Example: <kbd>https://verifier.login.persona.org/verify</kbd>.",
+ persona_includejs_url => "This is the URL needed by Persona to load the necessary " _
+ "javascript library for authentication. " _
+ "Example: <kbd>https://persona.org/include.js</kbd>."
+ }
+%]
diff --git a/extensions/Persona/template/en/default/admin/params/persona.html.tmpl b/extensions/Persona/template/en/default/admin/params/persona.html.tmpl
new file mode 100644
index 000000000..5c060129b
--- /dev/null
+++ b/extensions/Persona/template/en/default/admin/params/persona.html.tmpl
@@ -0,0 +1,22 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ title = "Persona"
+ desc = "Configure Persona Authentication"
+%]
+
+[% param_descs = {
+ persona_verify_url => "This is the URL for the Persona authority that the " _
+ "user will be verified against. " _
+ "Example: <kbd>https://verifier.login.persona.org/verify</kbd>.",
+ persona_includejs_url => "This is the URL needed by Persona to load the necessary " _
+ "javascript library for authentication. " _
+ "Example: <kbd>https://login.persona.org/include.js</kbd>."
+ }
+%]
diff --git a/extensions/Persona/template/en/default/hook/account/auth/login-additional_methods.html.tmpl b/extensions/Persona/template/en/default/hook/account/auth/login-additional_methods.html.tmpl
new file mode 100644
index 000000000..5be7910ad
--- /dev/null
+++ b/extensions/Persona/template/en/default/hook/account/auth/login-additional_methods.html.tmpl
@@ -0,0 +1,6 @@
+[% IF Param('user_info_class').split(',').contains('Persona')
+ && Param('persona_includejs_url') %]
+<p>
+ <img src="extensions/Persona/web/images/persona_sign_in.png" width="185" height="25" onclick="persona_sign_in()">
+</p>
+[% END %]
diff --git a/extensions/Persona/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl b/extensions/Persona/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl
new file mode 100644
index 000000000..5d8503d73
--- /dev/null
+++ b/extensions/Persona/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl
@@ -0,0 +1,17 @@
+[% IF Param('user_info_class').split(',').contains('Persona')
+ && Param('persona_includejs_url') %]
+<script type="text/javascript">
+ YAHOO.util.Event.addListener('login_link[% qs_suffix FILTER js %]','click', function () {
+ var login_link = YAHOO.util.Dom.get('persona_mini_login[% qs_suffix FILTER js %]');
+ YAHOO.util.Dom.removeClass(login_link, 'bz_default_hidden');
+ });
+ YAHOO.util.Event.addListener('hide_mini_login[% qs_suffix FILTER js %]','click', function () {
+ var login_link = YAHOO.util.Dom.get('persona_mini_login[% qs_suffix FILTER js %]');
+ YAHOO.util.Dom.addClass(login_link, 'bz_default_hidden');
+ });
+</script>
+<span id="persona_mini_login[% qs_suffix FILTER html %]" class="bz_default_hidden">
+ <img src="extensions/Persona/web/images/sign_in.png" height="22" width="75" align="absmiddle"
+ title="Sign in with Persona" onclick="persona_sign_in()"> or
+</span>
+[% END %]
diff --git a/extensions/Persona/template/en/default/hook/account/create-additional_methods.html.tmpl b/extensions/Persona/template/en/default/hook/account/create-additional_methods.html.tmpl
new file mode 100644
index 000000000..6b0d772af
--- /dev/null
+++ b/extensions/Persona/template/en/default/hook/account/create-additional_methods.html.tmpl
@@ -0,0 +1,18 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF Param('user_info_class').split(',').contains('Persona') %]
+Or, use your Persona account:
+<img src="extensions/Persona/web/images/sign_in.png" onclick="persona_create_account()"
+ width="95" height="25" align="absmiddle">
+
+<form id="persona_form" method="POST" action="index.cgi">
+ <input type="hidden" name="token" value="[% issue_hash_token(['login']) FILTER html %]">
+ <input type="hidden" name="persona_assertion" id="persona_assertion" value="">
+</form>
+[% END %]
diff --git a/extensions/Persona/template/en/default/hook/global/header-additional_header.html.tmpl b/extensions/Persona/template/en/default/hook/global/header-additional_header.html.tmpl
new file mode 100644
index 000000000..a2f150373
--- /dev/null
+++ b/extensions/Persona/template/en/default/hook/global/header-additional_header.html.tmpl
@@ -0,0 +1,84 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS Param('persona_includejs_url')
+ && Param('user_info_class').split(',').contains('Persona') %]
+
+[%# for now don't inject persona javascript on authenticated users.
+ # we've seen sessions being logged out unexpectedly
+ # we should only inject this code for users who used persona to authenicate %]
+[% RETURN IF user.id %]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+<script defer src="[% Param('persona_includejs_url') %]" type="text/javascript"></script>
+<script type="text/javascript">
+
+function createHidden(name, value, form) {
+ var field = document.createElement('input');
+ field.type = 'hidden';
+ field.name = name;
+ field.value = value;;
+ form.appendChild(field);
+}
+
+[% login_target = cgi.url("-relative" => 1, "-query" => 1) %]
+[% IF !login_target OR login_target.match("^token.cgi") %]
+ [% login_target = "index.cgi" %]
+[% END %]
+[% login_target = urlbase _ login_target %]
+
+[%# we only want to honour explicit login requests %]
+var persona_ignore_login = true;
+
+function persona_onlogin(assertion) {
+ if (persona_ignore_login)
+ return;
+ [% IF !user.id %]
+ var form = document.createElement('form');
+ form.action = '[% login_target FILTER js %]';
+ form.method = 'POST';
+ form.style.display = 'none';
+
+ createHidden('token', '[% issue_hash_token(['login']) FILTER js %]', form);
+ createHidden('Bugzilla_remember', 'on', form);
+ createHidden('persona_assertion', assertion, form);
+
+ [% FOREACH field = cgi.param() %]
+ [% NEXT IF field.search("^(Bugzilla_(login|password|restrictlogin)|token|persona_assertion)$") %]
+ [% FOREACH mvalue = cgi.param(field).slice(0) %]
+ createHidden('[% field FILTER js %]', '[% mvalue FILTER html_linebreak FILTER js %]', form);
+ [% END %]
+ [% END %]
+
+ document.body.appendChild(form);
+ form.submit();
+ [% END %]
+}
+
+YAHOO.util.Event.on(window, 'load', persona_init);
+function persona_init() {
+ navigator.id.watch({
+ [%# we can't set loggedInUser to user.login as this causes cgi authenticated
+ sessions to be logged out by persona %]
+ loggedInUser: null,
+ onlogin: persona_onlogin,
+ onlogout: function () {
+ [%# this should be redirecting to index.cgi?logout=1 however there's a
+ persona bug which causes this to break chrome and safari logins.
+ https://github.com/mozilla/browserid/issues/2423 %]
+ }
+ });
+}
+
+function persona_sign_in() {
+ persona_ignore_login = false;
+ navigator.id.request({ siteName: '[% terms.BugzillaTitle FILTER js %]' });
+}
+</script>
diff --git a/extensions/Persona/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/Persona/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..f2e5bda24
--- /dev/null
+++ b/extensions/Persona/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,12 @@
+[% IF error == "persona_account_too_powerful" %]
+ [% title = "Account Too Powerful" %]
+ Your account is a member of a group which is not permitted to use Persona to
+ log in. Please log in with your [% terms.Bugzilla %] username and password.
+ <br><br>
+ (Persona logins are disabled for accounts which are members of certain
+ particularly sensitive groups, while we gain experience with the technology.)
+[% ELSIF error == "persona_server_fail" %]
+ An error occurred during communication with the Persona servers:
+ <br>
+ [% reason FILTER html %]
+[% END %]
diff --git a/extensions/Persona/web/images/persona_sign_in.png b/extensions/Persona/web/images/persona_sign_in.png
new file mode 100644
index 000000000..ab88a7154
--- /dev/null
+++ b/extensions/Persona/web/images/persona_sign_in.png
Binary files differ
diff --git a/extensions/Persona/web/images/sign_in.png b/extensions/Persona/web/images/sign_in.png
new file mode 100644
index 000000000..82594ba82
--- /dev/null
+++ b/extensions/Persona/web/images/sign_in.png
Binary files differ
diff --git a/extensions/ProdCompSearch/Config.pm b/extensions/ProdCompSearch/Config.pm
new file mode 100644
index 000000000..c28b6d8f6
--- /dev/null
+++ b/extensions/ProdCompSearch/Config.pm
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ProdCompSearch;
+use strict;
+
+use constant NAME => 'ProdCompSearch';
+use constant REQUIRED_MODULES => [];
+use constant OPTIONAL_MODULES => [];
+
+__PACKAGE__->NAME;
diff --git a/extensions/ProdCompSearch/Extension.pm b/extensions/ProdCompSearch/Extension.pm
new file mode 100644
index 000000000..a5955fd8b
--- /dev/null
+++ b/extensions/ProdCompSearch/Extension.pm
@@ -0,0 +1,21 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ProdCompSearch;
+use strict;
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '1';
+
+sub webservice {
+ my ($self, $args) = @_;
+ my $dispatch = $args->{dispatch};
+ $dispatch->{PCS} = "Bugzilla::Extension::ProdCompSearch::WebService";
+}
+
+
+__PACKAGE__->NAME;
diff --git a/extensions/ProdCompSearch/lib/WebService.pm b/extensions/ProdCompSearch/lib/WebService.pm
new file mode 100644
index 000000000..2e2592879
--- /dev/null
+++ b/extensions/ProdCompSearch/lib/WebService.pm
@@ -0,0 +1,100 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ProdCompSearch::WebService;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::WebService);
+
+use Bugzilla::Error;
+use Bugzilla::Util qw(detaint_natural trick_taint);
+
+sub prod_comp_search {
+ my ($self, $params) = @_;
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->switch_to_shadow_db();
+
+ my $search = $params->{'search'};
+ $search || ThrowCodeError('param_required',
+ { function => 'PCS.prod_comp_search', param => 'search' });
+
+ my $limit = detaint_natural($params->{'limit'})
+ ? $dbh->sql_limit($params->{'limit'})
+ : '';
+
+ # We do this in the DB directly as we want it to be fast and
+ # not have the overhead of loading full product objects
+
+ # All products which the user has "Entry" access to.
+ my $enterable_ids = $dbh->selectcol_arrayref(
+ 'SELECT products.id FROM products
+ LEFT JOIN group_control_map
+ ON group_control_map.product_id = products.id
+ AND group_control_map.entry != 0
+ AND group_id NOT IN (' . $user->groups_as_string . ')
+ WHERE group_id IS NULL
+ AND products.isactive = 1');
+
+ if (scalar @$enterable_ids) {
+ # And all of these products must have at least one component
+ # and one version.
+ $enterable_ids = $dbh->selectcol_arrayref(
+ 'SELECT DISTINCT products.id FROM products
+ WHERE ' . $dbh->sql_in('products.id', $enterable_ids) .
+ ' AND products.id IN (SELECT DISTINCT components.product_id
+ FROM components
+ WHERE components.isactive = 1)
+ AND products.id IN (SELECT DISTINCT versions.product_id
+ FROM versions
+ WHERE versions.isactive = 1)');
+ }
+
+ return { products => [] } if !scalar @$enterable_ids;
+
+ my @list;
+ foreach my $word (split(/[\s,]+/, $search)) {
+ if ($word ne "") {
+ my $sql_word = $dbh->quote($word);
+ trick_taint($sql_word);
+ # note: CONCAT_WS is MySQL specific
+ my $field = "CONCAT_WS(' ', products.name, products.description,
+ components.name, components.description)";
+ push(@list, $dbh->sql_iposition($sql_word, $field) . " > 0");
+ }
+ }
+
+ my $products = $dbh->selectall_arrayref("
+ SELECT products.name AS product,
+ components.name AS component
+ FROM products
+ INNER JOIN components ON products.id = components.product_id
+ WHERE (" . join(" AND ", @list) . ")
+ AND products.id IN (" . join(",", @$enterable_ids) . ")
+ ORDER BY products.name $limit",
+ { Slice => {} });
+
+ # To help mozilla staff file bmo administration bugs into the right
+ # component, sort bmo in front of bugzilla.
+ if ($user->in_group('mozilla-corporation') || $user->in_group('mozilla-foundation')) {
+ $products = [
+ sort {
+ return 1 if $a->{product} eq 'Bugzilla'
+ && $b->{product} eq 'bugzilla.mozilla.org';
+ return -1 if $b->{product} eq 'Bugzilla'
+ && $a->{product} eq 'bugzilla.mozilla.org';
+ return lc($a->{product}) cmp lc($b->{product})
+ || lc($a->{component}) cmp lc($b->{component});
+ } @$products
+ ];
+ }
+
+ return { products => $products };
+}
+
+1;
diff --git a/extensions/ProdCompSearch/template/en/default/pages/prodcompsearch.html.tmpl b/extensions/ProdCompSearch/template/en/default/pages/prodcompsearch.html.tmpl
new file mode 100644
index 000000000..5b39315b5
--- /dev/null
+++ b/extensions/ProdCompSearch/template/en/default/pages/prodcompsearch.html.tmpl
@@ -0,0 +1,25 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "File a $terms.Bug"
+ javascript_urls = [ "js/yui3/yui/yui-min.js",
+ "extensions/ProdCompSearch/web/js/prod_comp_search.js" ]
+ style_urls = [ "extensions/ProdCompSearch/web/styles/prod_comp_search.css" ]
+%]
+
+<div id="prod_comp_search_main">
+ [% PROCESS prodcompsearch/form.html.tmpl
+ query_header = "File a $terms.Bug:"
+ script_name = "enter_bug.cgi"
+ %]
+</div>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/ProdCompSearch/template/en/default/prodcompsearch/form.html.tmpl b/extensions/ProdCompSearch/template/en/default/prodcompsearch/form.html.tmpl
new file mode 100644
index 000000000..8d4f46e07
--- /dev/null
+++ b/extensions/ProdCompSearch/template/en/default/prodcompsearch/form.html.tmpl
@@ -0,0 +1,34 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<script type="text/javascript">
+ [% IF script_name %]
+ ProdCompSearch.script_name = '[% script_name FILTER js %]';
+ [% END %]
+ [% IF format %]
+ ProdCompSearch.format = '[% format FILTER js %]';
+ [% END %]
+ [% IF cloned_bug_id %]
+ ProdCompSearch.cloned_bug_id = '[% cloned_bug_id FILTER js %]';
+ [% END %]
+ [% IF new_tab %]
+ ProdCompSearch.new_tab = true;
+ [% END %]
+</script>
+
+<div id="prod_comp_search_form" class="yui3-skin-sam">
+ <div id="prod_comp_search_header">
+ [% input_label FILTER none %]&nbsp;
+ <img id="prod_comp_throbber" src="extensions/ProdCompSearch/web/images/throbber.gif"
+ class="bz_default_hidden" width="16" height="11">
+ <span id="prod_comp_no_components" class="bz_default_hidden">
+ No components found</span>
+ </div>
+ <input id="prod_comp_search" type="text" size="50"
+ placeholder="Search by product and component keywords">
+</div>
diff --git a/extensions/ProdCompSearch/web/images/throbber.gif b/extensions/ProdCompSearch/web/images/throbber.gif
new file mode 100644
index 000000000..bc4fa6561
--- /dev/null
+++ b/extensions/ProdCompSearch/web/images/throbber.gif
Binary files differ
diff --git a/extensions/ProdCompSearch/web/js/prod_comp_search.js b/extensions/ProdCompSearch/web/js/prod_comp_search.js
new file mode 100644
index 000000000..7cb1ec73b
--- /dev/null
+++ b/extensions/ProdCompSearch/web/js/prod_comp_search.js
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+// Product and component search to file a new bug
+
+var ProdCompSearch = {
+ script_name: 'enter_bug.cgi',
+ script_choices: ['enter_bug.cgi', 'describecomponents.cgi'],
+ format: null,
+ cloned_bug_id: null,
+ new_tab: null
+};
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("node", "json-stringify", "autocomplete", "escape",
+ "datasource-io", "datasource-jsonschema", function (Y) {
+ var counter = 0,
+ dataSource = null,
+ autoComplete = null;
+
+ var resultListFormat = function(query, results) {
+ return Y.Array.map(results, function(result) {
+ var data = result.raw;
+ result.text = data.product + ' :: ' + data.component;
+ return Y.Escape.html(result.text);
+ });
+ };
+
+ var requestTemplate = function(query) {
+ counter = counter + 1;
+ var json_object = {
+ version: "1.1",
+ method : "PCS.prod_comp_search",
+ id : counter,
+ params : { search: query }
+ };
+ return Y.JSON.stringify(json_object);
+ };
+
+ var dataSource = new Y.DataSource.IO({
+ source: 'jsonrpc.cgi',
+ ioConfig: {
+ method: "POST",
+ headers: { 'Content-Type': 'application/json' }
+ }
+ });
+
+ dataSource.plug(Y.Plugin.DataSourceJSONSchema, {
+ schema: {
+ resultListLocator : "result.products",
+ resultFields : [ "product", "component" ]
+ }
+ });
+
+ var input = Y.one('#prod_comp_search');
+
+ input.plug(Y.Plugin.AutoComplete, {
+ activateFirstItem: false,
+ enableCache: true,
+ source: dataSource,
+ minQueryLength: 3,
+ queryDelay: 0.05,
+ resultFormatter: resultListFormat,
+ suppressInputUpdate: true,
+ maxResults: 25,
+ scrollIntoView: true,
+ requestTemplate: requestTemplate,
+ on: {
+ query: function(e) {
+ Y.one("#prod_comp_throbber").removeClass('bz_default_hidden');
+ Y.one("#prod_comp_no_components").addClass('bz_default_hidden');
+ },
+ results: function(e) {
+ Y.one("#prod_comp_throbber").addClass('bz_default_hidden');
+ input.ac.set('activateFirstItem', e.results.length == 1);
+ if (e.results.length == 0) {
+ Y.one("#prod_comp_no_components").removeClass('bz_default_hidden');
+ }
+ },
+ select: function(e) {
+ // Only redirect if the script_name is a valid choice
+ if (Y.Array.indexOf(ProdCompSearch.script_choices, ProdCompSearch.script_name) == -1)
+ return;
+
+ var data = e.result.raw;
+ var url = ProdCompSearch.script_name +
+ "?product=" + encodeURIComponent(data.product) +
+ "&component=" + encodeURIComponent(data.component);
+ if (ProdCompSearch.script_name == 'enter_bug.cgi') {
+ if (ProdCompSearch.format)
+ url += "&format=" + encodeURIComponent(ProdCompSearch.format);
+ if (ProdCompSearch.cloned_bug_id)
+ url += "&cloned_bug_id=" + encodeURIComponent(ProdCompSearch.cloned_bug_id);
+ }
+ if (ProdCompSearch.script_name == 'describecomponents.cgi') {
+ url += "#" + encodeURIComponent(data.component);
+ }
+ if (ProdCompSearch.new_tab) {
+ window.open(url, '_blank');
+ }
+ else {
+ window.location.href = url;
+ }
+ }
+ },
+ after: {
+ select: function(e) {
+ if (ProdCompSearch.new_tab) {
+ input.set('value','');
+ }
+ }
+ }
+ });
+
+ input.on('focus', function (e) {
+ if (e.target.value && e.target.value.length > 3) {
+ dataSource.load(e.target.value);
+ }
+ });
+});
diff --git a/extensions/ProdCompSearch/web/styles/prod_comp_search.css b/extensions/ProdCompSearch/web/styles/prod_comp_search.css
new file mode 100644
index 000000000..71829023c
--- /dev/null
+++ b/extensions/ProdCompSearch/web/styles/prod_comp_search.css
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#prod_comp_search_main {
+ width: 400px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+#prod_comp_search_form .yui3-aclist-input {
+ width: 360px;
+}
+
+#prod_comp_no_components {
+ color: red;
+}
diff --git a/extensions/ProductDashboard/Config.pm b/extensions/ProductDashboard/Config.pm
new file mode 100644
index 000000000..3a4654974
--- /dev/null
+++ b/extensions/ProductDashboard/Config.pm
@@ -0,0 +1,14 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ProductDashboard;
+
+use strict;
+
+use constant NAME => 'ProductDashboard';
+
+__PACKAGE__->NAME;
diff --git a/extensions/ProductDashboard/Extension.pm b/extensions/ProductDashboard/Extension.pm
new file mode 100644
index 000000000..1e6ddffe9
--- /dev/null
+++ b/extensions/ProductDashboard/Extension.pm
@@ -0,0 +1,200 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ProductDashboard;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+use Bugzilla::Error;
+use Bugzilla::Product;
+use Bugzilla::Field;
+
+use Bugzilla::Extension::ProductDashboard::Queries;
+use Bugzilla::Extension::ProductDashboard::Util;
+
+our $VERSION = BUGZILLA_VERSION;
+
+sub page_before_template {
+ my ($self, $args) = @_;
+
+ my $page = $args->{page_id};
+ my $vars = $args->{vars};
+
+ if ($page =~ m{^productdashboard\.}) {
+ _page_dashboard($vars);
+ }
+}
+
+sub _page_dashboard {
+ my $vars = shift;
+
+ my $cgi = Bugzilla->cgi;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ # Switch to shadow db since we are just reading information
+ Bugzilla->switch_to_shadow_db();
+
+ # All pages point to the same part of the documentation.
+ $vars->{'doc_section'} = 'bugreports.html';
+
+ # Forget any previously selected product
+ $cgi->send_cookie(-name => 'PRODUCT_DASHBOARD',
+ -value => 'X',
+ -expires => "Fri, 01-Jan-1970 00:00:00 GMT");
+
+ # If the user cannot enter bugs in any product, stop here.
+ scalar @{$user->get_selectable_products}
+ || ThrowUserError('no_products');
+
+ # Create data structures representing each classification
+ my @classifications = ();
+ foreach my $c (@{$user->get_selectable_classifications}) {
+ # Create hash to hold attributes for each classification.
+ my %classification = (
+ 'name' => $c->name,
+ 'products' => [ @{$user->get_selectable_products($c->id)} ]
+ );
+ # Assign hash back to classification array.
+ push @classifications, \%classification;
+ }
+ $vars->{'classifications'} = \@classifications;
+
+ my $product_name = trim($input->{'product'} || '');
+
+ if (!$product_name && $cgi->cookie('PRODUCT_DASHBOARD')) {
+ $product_name = $cgi->cookie('PRODUCT_DASHBOARD');
+ }
+
+ return if !$product_name;
+
+ # Do not use Bugzilla::Product::check_product() here, else the user
+ # could know whether the product doesn't exist or is not accessible.
+ my $product = new Bugzilla::Product({'name' => $product_name});
+
+ # We need to check and make sure that the user has permission
+ # to enter a bug against this product.
+ if (!$product || !$user->can_enter_product($product->name)) {
+ return;
+ }
+
+ # Remember selected product
+ $cgi->send_cookie(-name => 'PRODUCT_DASHBOARD',
+ -value => $product->name,
+ -expires => "Fri, 01-Jan-2038 00:00:00 GMT");
+
+ my $current_tab_name = $input->{'tab'} || "summary";
+ trick_taint($current_tab_name);
+ $vars->{'current_tab_name'} = $current_tab_name;
+
+ my $bug_status = trim($input->{'bug_status'} || 'open');
+
+ $vars->{'bug_status'} = $bug_status;
+ $vars->{'product'} = $product;
+ $vars->{'bug_link_all'} = bug_link_all($product);
+ $vars->{'bug_link_open'} = bug_link_open($product);
+ $vars->{'bug_link_closed'} = bug_link_closed($product);
+ $vars->{'total_bugs'} = total_bugs($product);
+ $vars->{'total_open_bugs'} = total_open_bugs($product);
+ $vars->{'total_closed_bugs'} = total_closed_bugs($product);
+ $vars->{'severities'} = get_legal_field_values('bug_severity');
+
+ if ($vars->{'total_bugs'}) {
+ $vars->{'open_bugs_percentage'}
+ = int($vars->{'total_open_bugs'} / $vars->{'total_bugs'} * 100);
+ $vars->{'closed_bugs_percentage'}
+ = int($vars->{'total_closed_bugs'} / $vars->{'total_bugs'} * 100);
+ }
+ else {
+ $vars->{'open_bugs_percentage'} = 0;
+ $vars->{'closed_bugs_percentage'} = 0;
+ }
+
+ if ($current_tab_name eq 'summary') {
+ $vars->{'by_priority'} = by_priority($product, $bug_status);
+ $vars->{'by_severity'} = by_severity($product, $bug_status);
+ $vars->{'by_assignee'} = by_assignee($product, $bug_status, 50);
+ $vars->{'by_status'} = by_status($product, $bug_status);
+ }
+
+ if ($current_tab_name eq 'recents') {
+ my $recent_days = $input->{'recent_days'} || 7;
+ (detaint_natural($recent_days) && $recent_days > 0 && $recent_days < 101)
+ || ThrowUserError('product_dashboard_invalid_recent_days');
+
+ my $params = {
+ product => $product,
+ days => $recent_days,
+ date_from => $input->{'date_from'} || '',
+ date_to => $input->{'date_to'} || '',
+ };
+
+ $vars->{'recently_opened'} = recently_opened($params);
+ $vars->{'recently_closed'} = recently_closed($params);
+ $vars->{'recent_days'} = $recent_days;
+ $vars->{'date_from'} = $input->{'date_from'};
+ $vars->{'date_to'} = $input->{'date_to'};
+ }
+
+ if ($current_tab_name eq 'components') {
+ if ($input->{'component'}) {
+ $vars->{'summary'} = by_value_summary($product, 'component', $input->{'component'}, $bug_status);
+ $vars->{'summary'}{'type'} = 'component';
+ $vars->{'summary'}{'value'} = $input->{'component'};
+ }
+ elsif ($input->{'version'}) {
+ $vars->{'summary'} = by_value_summary($product, 'version', $input->{'version'}, $bug_status);
+ $vars->{'summary'}{'type'} = 'version';
+ $vars->{'summary'}{'value'} = $input->{'version'};
+ }
+ elsif ($input->{'target_milestone'} && Bugzilla->params->{'usetargetmilestone'}) {
+ $vars->{'summary'} = by_value_summary($product, 'target_milestone', $input->{'target_milestone'}, $bug_status);
+ $vars->{'summary'}{'type'} = 'target_milestone';
+ $vars->{'summary'}{'value'} = $input->{'target_milestone'};
+ }
+ else {
+ $vars->{'by_component'} = by_component($product, $bug_status);
+ $vars->{'by_version'} = by_version($product, $bug_status);
+ if (Bugzilla->params->{'usetargetmilestone'}) {
+ $vars->{'by_milestone'} = by_milestone($product, $bug_status);
+ }
+ }
+ }
+
+ if ($current_tab_name eq 'duplicates') {
+ $vars->{'by_duplicate'} = by_duplicate($product, $bug_status);
+ }
+
+ if ($current_tab_name eq 'popularity') {
+ $vars->{'by_popularity'} = by_popularity($product, $bug_status);
+ }
+
+ if ($current_tab_name eq 'roadmap') {
+ foreach my $milestone (@{$product->milestones}){
+ my %milestone_stats;
+ $milestone_stats{'name'} = $milestone->name;
+ $milestone_stats{'total_bugs'} = total_bug_milestone($product, $milestone);
+ $milestone_stats{'open_bugs'} = bug_milestone_by_status($product, $milestone, 'open');
+ $milestone_stats{'closed_bugs'} = bug_milestone_by_status($product, $milestone, 'closed');
+ $milestone_stats{'link_total'} = bug_milestone_link_total($product, $milestone);
+ $milestone_stats{'link_open'} = bug_milestone_link_open($product, $milestone);
+ $milestone_stats{'link_closed'} = bug_milestone_link_closed($product, $milestone);
+ $milestone_stats{'percentage'} = $milestone_stats{'total_bugs'}
+ ? int(($milestone_stats{'closed_bugs'} / $milestone_stats{'total_bugs'}) * 100)
+ : 0;
+ push (@{$vars->{'by_roadmap'}}, \%milestone_stats);
+ }
+ }
+}
+
+__PACKAGE__->NAME;
+
diff --git a/extensions/ProductDashboard/lib/Queries.pm b/extensions/ProductDashboard/lib/Queries.pm
new file mode 100644
index 000000000..b58298ea8
--- /dev/null
+++ b/extensions/ProductDashboard/lib/Queries.pm
@@ -0,0 +1,475 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::ProductDashboard::Queries;
+
+use strict;
+
+use base qw(Exporter);
+@Bugzilla::Extension::ProductDashboard::Queries::EXPORT = qw(
+ total_bugs
+ total_open_bugs
+ total_closed_bugs
+ by_version
+ by_value_summary
+ by_milestone
+ by_priority
+ by_severity
+ by_component
+ by_assignee
+ by_status
+ by_duplicate
+ by_popularity
+ recently_opened
+ recently_closed
+ total_bug_milestone
+ bug_milestone_by_status
+);
+
+use Bugzilla::CGI;
+use Bugzilla::User;
+use Bugzilla::Util;
+use Bugzilla::Component;
+use Bugzilla::Version;
+use Bugzilla::Milestone;
+
+use Bugzilla::Extension::ProductDashboard::Util qw(open_states closed_states
+ quoted_open_states quoted_closed_states);
+
+sub total_bugs {
+ my $product = shift;
+ my $dbh = Bugzilla->dbh;
+
+ return $dbh->selectrow_array("SELECT COUNT(bug_id)
+ FROM bugs
+ WHERE product_id = ?", undef, $product->id);
+}
+
+sub total_open_bugs {
+ my $product = shift;
+ my $bug_status = shift;
+ my $dbh = Bugzilla->dbh;
+
+ return $dbh->selectrow_array("SELECT COUNT(bug_id)
+ FROM bugs
+ WHERE bug_status IN (" . join(',', quoted_open_states()) . ")
+ AND product_id = ?", undef, $product->id);
+}
+
+sub total_closed_bugs {
+ my $product = shift;
+ my $dbh = Bugzilla->dbh;
+
+ return $dbh->selectrow_array("SELECT COUNT(bug_id)
+ FROM bugs
+ WHERE bug_status IN (" . join(',', quoted_closed_states()) . ")
+ AND product_id = ?", undef, $product->id);
+}
+
+sub bug_link_all {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name);
+}
+
+sub bug_link_open {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) . "&bug_status=__open__";
+}
+
+sub bug_link_closed {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) . "&bug_status=__closed__";
+}
+
+sub by_version {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT version, COUNT(bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs
+ WHERE product_id = ?
+ $extra
+ GROUP BY version
+ ORDER BY COUNT(bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub by_milestone {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT target_milestone, COUNT(bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs
+ WHERE product_id = ?
+ $extra
+ GROUP BY target_milestone
+ ORDER BY COUNT(bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub by_priority {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT priority, COUNT(bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs
+ WHERE product_id = ?
+ $extra
+ GROUP BY priority
+ ORDER BY COUNT(bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub by_severity {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT bug_severity, COUNT(bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs
+ WHERE product_id = ?
+ $extra
+ GROUP BY bug_severity
+ ORDER BY COUNT(bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub by_component {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT components.name, COUNT(bugs.bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs INNER JOIN components ON bugs.component_id = components.id
+ WHERE bugs.product_id = ?
+ $extra
+ GROUP BY components.name
+ ORDER BY COUNT(bugs.bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub by_value_summary {
+ my ($product, $type, $value, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $query = "SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.version AS version,
+ components.name AS component,
+ bugs.bug_severity AS severity,
+ bugs.short_desc AS summary
+ FROM bugs, components
+ WHERE bugs.product_id = ?
+ AND bugs.component_id = components.id ";
+
+ if ($type eq 'component') {
+ Bugzilla::Component->check({ product => $product, name => $value });
+ $query .= "AND components.name = ? " if $type eq 'component';
+ }
+ elsif ($type eq 'version') {
+ Bugzilla::Version->check({ product => $product, name => $value });
+ $query .= "AND bugs.version = ? " if $type eq 'version';
+ }
+ elsif ($type eq 'target_milestone') {
+ Bugzilla::Milestone->check({ product => $product, name => $value });
+ $query .= "AND bugs.target_milestone = ? " if $type eq 'target_milestone';
+ }
+
+ $query .= "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ") " if $bug_status eq 'open';
+ $query .= "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ") " if $bug_status eq 'closed';
+
+ trick_taint($value);
+
+ my $past_due_bugs = $dbh->selectall_arrayref($query .
+ "AND (bugs.deadline IS NOT NULL AND bugs.deadline != '')
+ AND bugs.deadline < now() ORDER BY bugs.deadline LIMIT 10",
+ {'Slice' => {}}, $product->id, $value);
+
+ my $updated_recently_bugs = $dbh->selectall_arrayref($query .
+ "AND bugs.delta_ts != bugs.creation_ts " .
+ "ORDER BY bugs.delta_ts DESC LIMIT 10",
+ {'Slice' => {}}, $product->id, $value);
+
+ my $timestamp = $dbh->selectrow_array("SELECT " . $dbh->sql_date_format("LOCALTIMESTAMP(0)", "%Y-%m-%d"));
+
+ return {
+ timestamp => $timestamp,
+ past_due => _filter_bugs($past_due_bugs),
+ updated_recently => _filter_bugs($updated_recently_bugs),
+ };
+}
+
+sub by_assignee {
+ my ($product, $bug_status, $limit) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $limit = ($limit && detaint_natural($limit)) ? $dbh->sql_limit($limit) : "";
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ my @result = map { [ Bugzilla::User->new($_->[0]), $_->[1], $_->[2] ] }
+ @{$dbh->selectall_arrayref("SELECT bugs.assigned_to AS userid, COUNT(bugs.bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs, profiles
+ WHERE bugs.product_id = ?
+ AND bugs.assigned_to = profiles.userid
+ $extra
+ GROUP BY profiles.login_name
+ ORDER BY COUNT(bugs.bug_id) DESC $limit",
+ undef, $product->id, $product->id)};
+
+ return \@result;
+}
+
+sub by_status {
+ my ($product, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectall_arrayref("SELECT bugs.bug_status, COUNT(bugs.bug_id),
+ ROUND(((COUNT(bugs.bug_id) / ( SELECT COUNT(*) FROM bugs WHERE bugs.product_id = ? $extra)) * 100))
+ FROM bugs
+ WHERE bugs.product_id = ?
+ $extra
+ GROUP BY bugs.bug_status
+ ORDER BY COUNT(bugs.bug_id) DESC",
+ undef, $product->id, $product->id);
+}
+
+sub total_bug_milestone {
+ my ($product, $milestone) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return $dbh->selectrow_array("SELECT COUNT(bug_id)
+ FROM bugs
+ WHERE target_milestone = ?
+ AND product_id = ?",
+ undef, $milestone->name, $product->id);
+}
+
+sub bug_milestone_by_status {
+ my ($product, $milestone, $bug_status) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $extra = '';
+
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ return $dbh->selectrow_array("SELECT COUNT(bug_id)
+ FROM bugs
+ WHERE target_milestone = ?
+ AND product_id = ? $extra",
+ undef,
+ $milestone->name,
+ $product->id);
+
+}
+
+sub by_duplicate {
+ my ($product, $bug_status, $limit) = @_;
+ my $dbh = Bugzilla->dbh;
+ $limit = ($limit && detaint_natural($limit)) ? $dbh->sql_limit($limit) : "";
+
+ my $extra = '';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ my $unfiltered_bugs = $dbh->selectall_arrayref("SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.version AS version,
+ components.name AS component,
+ bugs.bug_severity AS severity,
+ bugs.short_desc AS summary,
+ COUNT(duplicates.dupe) AS dupe_count
+ FROM bugs, duplicates, components
+ WHERE bugs.product_id = ?
+ AND bugs.component_id = components.id
+ AND bugs.bug_id = duplicates.dupe_of
+ $extra
+ GROUP BY bugs.bug_id, bugs.bug_status, components.name,
+ bugs.bug_severity, bugs.short_desc
+ HAVING COUNT(duplicates.dupe) > 1
+ ORDER BY COUNT(duplicates.dupe) DESC $limit",
+ {'Slice' => {}}, $product->id);
+
+ return _filter_bugs($unfiltered_bugs);
+}
+
+sub by_popularity {
+ my ($product, $bug_status, $limit) = @_;
+ my $dbh = Bugzilla->dbh;
+ $limit = ($limit && detaint_natural($limit)) ? $dbh->sql_limit($limit) : "";
+
+ my $extra = '';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")" if $bug_status eq 'open';
+ $extra = "AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")" if $bug_status eq 'closed';
+
+ my $unfiltered_bugs = $dbh->selectall_arrayref("SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.version AS version,
+ components.name AS component,
+ bugs.bug_severity AS severity,
+ bugs.short_desc AS summary,
+ bugs.votes AS votes
+ FROM bugs, components
+ WHERE bugs.product_id = ?
+ AND bugs.component_id = components.id
+ AND bugs.votes > 1
+ $extra
+ ORDER BY bugs.votes DESC $limit",
+ {'Slice' => {}}, $product->id);
+
+ return _filter_bugs($unfiltered_bugs);
+}
+
+sub recently_opened {
+ my ($params) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $product = $params->{'product'};
+ my $days = $params->{'days'};
+ my $limit = $params->{'limit'};
+ my $date_from = $params->{'date_from'};
+ my $date_to = $params->{'date_to'};
+
+ $days ||= 7;
+ $limit = ($limit && detaint_natural($limit)) ? $dbh->sql_limit($limit) : "";
+
+ my @values = ($product->id);
+
+ my $date_part;
+ if ($date_from && $date_to) {
+ validate_date($date_from)
+ || ThrowUserError('illegal_date', { date => $date_from,
+ format => 'YYYY-MM-DD' });
+ validate_date($date_to)
+ || ThrowUserError('illegal_date', { date => $date_to,
+ format => 'YYYY-MM-DD' });
+ $date_part = "AND bugs.creation_ts >= ? AND bugs.creation_ts <= ?";
+ push(@values, trick_taint($date_from), trick_taint($date_to));
+ }
+ else {
+ $date_part = "AND bugs.creation_ts >= CURRENT_DATE() - INTERVAL ? DAY";
+ push(@values, $days);
+ }
+
+ my $unfiltered_bugs = $dbh->selectall_arrayref("SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.version AS version,
+ components.name AS component,
+ bugs.bug_severity AS severity,
+ bugs.short_desc AS summary
+ FROM bugs, components
+ WHERE bugs.product_id = ?
+ AND bugs.component_id = components.id
+ AND bugs.bug_status IN (" . join(',', quoted_open_states()) . ")
+ $date_part
+ ORDER BY bugs.bug_id DESC $limit",
+ {'Slice' => {}}, @values);
+
+ return _filter_bugs($unfiltered_bugs);
+}
+
+sub recently_closed {
+ my ($params) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $product = $params->{'product'};
+ my $days = $params->{'days'};
+ my $limit = $params->{'limit'};
+ my $date_from = $params->{'date_from'};
+ my $date_to = $params->{'date_to'};
+
+ $days ||= 7;
+ $limit = ($limit && detaint_natural($limit)) ? $dbh->sql_limit($limit) : "";
+
+ my @values = ($product->id);
+
+ my $date_part;
+ if ($date_from && $date_to) {
+ validate_date($date_from)
+ || ThrowUserError('illegal_date', { date => $date_from,
+ format => 'YYYY-MM-DD' });
+ validate_date($date_to)
+ || ThrowUserError('illegal_date', { date => $date_to,
+ format => 'YYYY-MM-DD' });
+ $date_part = "AND bugs_activity.bug_when >= ? AND bugs_activity.bug_when <= ?";
+ push(@values, trick_taint($date_from), trick_taint($date_to));
+ }
+ else {
+ $date_part = "AND bugs_activity.bug_when >= CURRENT_DATE() - INTERVAL ? DAY";
+ push(@values, $days);
+ }
+
+ my $unfiltered_bugs = $dbh->selectall_arrayref("SELECT DISTINCT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.version AS version,
+ components.name AS component,
+ bugs.bug_severity AS severity,
+ bugs.short_desc AS summary
+ FROM bugs, components, bugs_activity
+ WHERE bugs.product_id = ?
+ AND bugs.component_id = components.id
+ AND bugs.bug_status IN (" . join(',', quoted_closed_states()) . ")
+ AND bugs.bug_id = bugs_activity.bug_id
+ AND bugs_activity.added IN (" . join(',', quoted_closed_states()) . ")
+ $date_part
+ ORDER BY bugs.bug_id DESC $limit",
+ {'Slice' => {}}, @values);
+
+ return _filter_bugs($unfiltered_bugs);
+}
+
+sub _filter_bugs {
+ my ($unfiltered_bugs) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return [] if !$unfiltered_bugs;
+
+ my @unfiltered_bug_ids = map { $_->{'id'} } @$unfiltered_bugs;
+ my %filtered_bug_ids = map { $_ => 1 } @{ Bugzilla->user->visible_bugs(\@unfiltered_bug_ids) };
+
+ my @filtered_bugs;
+ foreach my $bug (@$unfiltered_bugs) {
+ next if !$filtered_bug_ids{$bug->{'id'}};
+ push(@filtered_bugs, $bug);
+ }
+
+ return \@filtered_bugs;
+}
+
+1;
diff --git a/extensions/ProductDashboard/lib/Util.pm b/extensions/ProductDashboard/lib/Util.pm
new file mode 100644
index 000000000..5d9c161ef
--- /dev/null
+++ b/extensions/ProductDashboard/lib/Util.pm
@@ -0,0 +1,95 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Extension::ProductDashboard::Util;
+
+use strict;
+
+use base qw(Exporter);
+@Bugzilla::Extension::ProductDashboard::Util::EXPORT = qw(
+ bug_link_all
+ bug_link_open
+ bug_link_closed
+ open_states
+ closed_states
+ quoted_open_states
+ quoted_closed_states
+ bug_milestone_link_total
+ bug_milestone_link_open
+ bug_milestone_link_closed
+);
+
+use Bugzilla::Status;
+use Bugzilla::Util;
+
+our $_open_states;
+sub open_states {
+ $_open_states ||= Bugzilla::Status->match({ is_open => 1, isactive => 1 });
+ return wantarray ? @$_open_states : $_open_states;
+}
+
+our $_quoted_open_states;
+sub quoted_open_states {
+ my $dbh = Bugzilla->dbh;
+ $_quoted_open_states ||= [ map { $dbh->quote($_->name) } open_states() ];
+ return wantarray ? @$_quoted_open_states : $_quoted_open_states;
+}
+
+our $_closed_states;
+sub closed_states {
+ $_closed_states ||= Bugzilla::Status->match({ is_open => 0, isactive => 1 });
+ return wantarray ? @$_closed_states : $_closed_states;
+}
+
+our $_quoted_closed_states;
+sub quoted_closed_states {
+ my $dbh = Bugzilla->dbh;
+ $_quoted_closed_states ||= [ map { $dbh->quote($_->name) } closed_states() ];
+ return wantarray ? @$_quoted_closed_states : $_quoted_closed_states;
+}
+
+sub bug_link_all {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name);
+}
+
+sub bug_link_open {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) .
+ "&bug_status=__open__";
+}
+
+sub bug_link_closed {
+ my $product = shift;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) .
+ "&bug_status=__closed__";
+}
+
+sub bug_milestone_link_total {
+ my ($product, $milestone) = @_;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) .
+ "&target_milestone=" . url_quote($milestone->name);
+}
+
+sub bug_milestone_link_open {
+ my ($product, $milestone) = @_;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) .
+ "&target_milestone=" . url_quote($milestone->name) . "&bug_status=__open__";
+}
+
+sub bug_milestone_link_closed {
+ my ($product, $milestone) = @_;
+
+ return correct_urlbase() . 'buglist.cgi?product=' . url_quote($product->name) .
+ "&target_milestone=" . url_quote($milestone->name) . "&bug_status=__closed__";
+}
+
+1;
diff --git a/extensions/ProductDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl b/extensions/ProductDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl
new file mode 100644
index 000000000..e9be8a13d
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/hook/global/common-links-action-links.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+ <li><span class="separator"> | </span><a href="page.cgi?id=productdashboard.html">Product Dashboard</a></li>
diff --git a/extensions/ProductDashboard/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/ProductDashboard/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..d8af64d31
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "product_dashboard_invalid_recent_days" %]
+ [% title = "Invalid Recent Days" %]
+ Invalid value for recent days.
+[% END %]
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard.html.tmpl
new file mode 100644
index 000000000..82de063aa
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard.html.tmpl
@@ -0,0 +1,237 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% javascript_urls = [ "js/yui3/yui/yui-min.js",
+ "js/util.js",
+ "js/field.js" ]
+%]
+
+[% IF current_tab_name == 'summary' %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/summary.js") %]
+ [% ELSIF current_tab_name == 'recents' %]
+ [% yui = [ "calendar" ] %]
+ [% javascript_urls.push("js/field.js") %]
+ [% javascript_urls.push("js/util.js") %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/recents.js") %]
+[% ELSIF current_tab_name == 'components' %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/components.js") %]
+[% ELSIF current_tab_name == 'duplicates' %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/duplicates.js") %]
+[% ELSIF current_tab_name == 'popularity' %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/popularity.js") %]
+[% ELSIF current_tab_name == 'roadmap' && Param('usetargetmilestone') %]
+ [% javascript_urls.push("extensions/ProductDashboard/web/js/roadmap.js") %]
+[% END %]
+
+[% filtered_product = product.name FILTER html %]
+[% PROCESS global/header.html.tmpl
+ title = "Product Dashboard: $filtered_product"
+ style_urls = [ "skins/standard/buglist.css",
+ "js/yui/assets/skins/sam/paginator.css",
+ "extensions/ProductDashboard/web/styles/productdashboard.css" ]
+%]
+
+<script type="text/javascript">
+<!--
+ PD = {};
+ [%# Set up severities list for proper sorting %]
+ PD.severities = new Array();
+ [% sort_count = 0 %]
+ [% FOREACH s = severities %]
+ PD.severities['[% s FILTER js %]'] = [% sort_count FILTER js %];
+ [% sort_count = sort_count + 1 %]
+ [% END %]
+-->
+</script>
+
+[% url_filtered_product = product.name FILTER uri %]
+[% url_filtered_status = bug_status FILTER uri %]
+
+[% tabs = [
+ {
+ name => "summary",
+ label => "Summary",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=summary"
+ },
+ {
+ name => "recents",
+ label => "Recents",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=recents"
+ },
+ {
+ name => "components",
+ label => "Components/Versions",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=components"
+ },
+ {
+ name => "duplicates",
+ label => "Duplicates",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=duplicates"
+ },
+ {
+ name => "roadmap",
+ label => "Road Map",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=roadmap"
+ },
+ ]
+%]
+
+[% IF product.votesperuser %]
+ [%
+ tabs.push({
+ name => "popularity",
+ label => "Popularity",
+ link => "page.cgi?id=productdashboard.html&product=$url_filtered_product&bug_status=$url_filtered_status&tab=popularity"
+ })
+ %]
+[% END %]
+
+[% FOREACH tab IN tabs %]
+ [% IF tab.name == current_tab_name %]
+ [% current_tab = tab %]
+ [% LAST %]
+ [% END %]
+[% END %]
+
+[% full_bug_count = 0 %]
+[% IF bug_status == 'open' %]
+ [% full_bug_count = total_open_bugs %]
+[% ELSIF bug_status == 'closed' %]
+ [% full_bug_count = total_closed_bugs %]
+[% ELSE %]
+ [% full_bug_count = total_bugs %]
+[% END %]
+
+[% bug_link = bug_link_all %]
+[% IF bug_status == 'open' %]
+ [% bug_link = bug_link_open %]
+[% ELSIF bug_status == 'closed' %]
+ [% bug_link = bug_link_closed %]
+[% END %]
+
+<div class="yui3-skin-sam">
+ <a name="top"></a>
+
+ <form action="page.cgi" method="get">
+ <input type="hidden" name="id" value="productdashboard.html">
+ <input type="hidden" name="tab" value="[% current_tab.name FILTER html %]">
+
+ [% IF summary.keys %]
+ <input type="hidden" name="[% summary.type FILTER html %]" value="[% summary.value FILTER html %]">
+ [% END %]
+
+ [% IF product %]
+ <span id="product_dashboard_links">
+ <ul>
+ <li><a href="[% urlbase FILTER none %]enter_bug.cgi?product=[% product.name FILTER uri %]">
+ Create a new [% terms.bug %] in this product</a></li>
+ <li><a href="[% urlbase FILTER none %]describecomponents.cgi?product=[% product.name FILTER uri %]">
+ Show full component descriptions for this product</a></li>
+ </ul>
+ </span>
+ [% END %]
+
+ <strong>Choose product:</strong>
+ <select name="product">
+ [% FOREACH c = classifications %]
+ <optgroup label="[% c.name FILTER html %]">
+ [% FOREACH p = c.products %]
+ <option value="[% p.name FILTER html %]"
+ [% IF p.name == product.name %]selected="selected"[% END %]>
+ [% p.name FILTER html %]</option>
+ [% END %]</optgroup>
+ [% END %]
+ </select>
+ <select name="bug_status" id="bug_status">
+ [% statuses = [ { name = 'open', label = "Open $terms.Bugs" },
+ { name = 'closed', label = "Closed $terms.Bugs" },
+ { name = 'all', label = "All $terms.Bugs" } ] %]
+ [% FOREACH status = statuses %]
+ <option value="[% status.name FILTER html %]"
+ [% " selected" IF bug_status == "${status.name}" %]>
+ [% status.label FILTER html %]
+ </option>
+ [% END %]
+ </select>
+
+ <input type="submit" value="[% IF product %]Change[% ELSE %]Submit[% END %]">
+
+ [% IF product %]
+ <div class="product_name">
+ [% product.name FILTER html %]
+ </div>
+
+ <div class="product_description">
+ [% product.description FILTER none %]
+ </div>
+
+ [% WRAPPER global/tabs.html.tmpl
+ tabs = tabs
+ current_tab = current_tab
+ %]
+
+ [% IF current_tab.name == 'summary' %]
+ [% PROCESS pages/productdashboard/summary.html.tmpl %]
+ [% END %]
+
+ [% IF current_tab.name == 'recents' %]
+ [% PROCESS pages/productdashboard/recents.html.tmpl %]
+ [% END %]
+
+ [% IF current_tab.name == 'components' %]
+ [% PROCESS pages/productdashboard/components.html.tmpl %]
+ [% END %]
+
+ [% IF current_tab.name == 'duplicates' %]
+ [% PROCESS pages/productdashboard/duplicates.html.tmpl %]
+ [% END %]
+
+ [% IF current_tab.name == 'popularity' %]
+ [% PROCESS pages/productdashboard/popularity.html.tmpl %]
+ [% END %]
+
+ [% IF current_tab.name == 'roadmap' && Param('usetargetmilestone') %]
+ [% PROCESS pages/productdashboard/roadmap.html.tmpl %]
+ [% END %]
+
+ [% END %][%# END WRAPPER %]
+ [% END %]
+
+ </form>
+</div>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK bar_graph %]
+ [% IF full_bug_count > 0 %][%# No divide by zero %]
+ [% percentage_bugs = (count / full_bug_count) * 100 FILTER format('%02.2f') %]
+ [% ELSE %]
+ [% percentage_bugs = 0 %]
+ [% END %]
+ <div class="bar_graph">
+ <table cellpadding="0" cellspacing="0" width="300px">
+ <tr>
+ <td width="[% percentage_bugs FILTER html %]%">
+ <table cellpadding="0" cellspacing="0" width="100%">
+ <tr>
+ <td bgcolor="#3c78b5">
+ <a title="[% percentage_bugs FILTER html %]%">
+ <img src="extensions/ProductDashboard/web/images/spacer.gif" height=10 width="100%" title="[% percentage_bugs FILTER html %]%">
+ </a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td width="[% 100 - percentage_bugs FILTER html %]%">&nbsp;&nbsp;&nbsp;[% percentage_bugs FILTER html %]%</td>
+ </tr>
+ </table>
+ </div>
+[% END %]
+
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/components.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/components.html.tmpl
new file mode 100644
index 000000000..6b0e7240a
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/components.html.tmpl
@@ -0,0 +1,146 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF summary.keys %]
+
+<h3>Summary for [% summary.type FILTER html %]: [% summary.value FILTER html %]</h3>
+
+<script>
+<!--
+ // Past due
+ [% IF user.is_timetracker %]
+ PD.past_due = [
+ [% FOREACH bug = summary.past_due %]
+ {
+ id: '[% bug.id FILTER js %]',
+ bug_status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+ [% END %]
+
+ // Updated recently
+ PD.updated_recently = [
+ [% FOREACH bug = summary.updated_recently %]
+ {
+ id: '[% bug.id FILTER js %]',
+ bug_status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+-->
+</script>
+
+[% IF user.is_timetracker %]
+ <p>
+ <a href="#past_due">Past Due</a> |
+ <a href="#updated_recently">Updated Recently</a>
+ </p>
+[% END %]
+
+<div class="yui3-skin-sam">
+
+ [% IF user.is_timetracker %]
+ <a name="past_due"></a>
+ <b>[% summary.past_due.size FILTER html %] Past Due [% terms.Bugs %]</b> (deadline is before today's date)
+ (<a href="[% bug_link FILTER html %]&amp;[% summary.type FILTER uri %]=[% summary.value FILTER uri %]&field0-0-0=deadline&type0-0-0=lessthan&value0-0-0=[% summary.timestamp FILTER uri %]&order=deadline">full list</a>)
+ <div id="past_due"></div>
+ <br>
+ [% END %]
+
+ <a name="updated_recently"></a>
+ <b>[% summary.updated_recently.size FILTER html %] Most Recently Updated [% terms.Bugs %]</b>
+ [% IF user.is_timetracker %](<a href="#top">back to top</a>)[% END %]
+ (<a href="[% bug_link FILTER html %]&amp;[% summary.type FILTER uri %]=[% summary.value FILTER uri %]&order=changeddate DESC">full list</a>)
+ <div id="updated_recently"></div>
+</div>
+
+[% ELSE %]
+
+<script type="text/javascript">
+<!--
+ PD.product_name = '[% product.name FILTER js %]';
+ PD.bug_status = '[% bug_status FILTER js %]';
+
+ // Component counts
+ PD.component_counts = [
+ [% FOREACH col = by_component %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link FILTER html %]&amp;component=[% col.0 FILTER uri %]">Link</a>'
+ },
+ [% END %]
+ ];
+
+ // Version counts
+ PD.version_counts = [
+ [% FOREACH col = by_version %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link FILTER html %]&amp;version=[% col.0 FILTER uri %]">Link</a>'
+ },
+ [% END %]
+ ];
+
+ [% IF Param('usetargetmilestone') %]
+ // Milestone counts
+ PD.milestone_counts = [
+ [% FOREACH col = by_milestone %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link FILTER html %]&amp;target_milestone=[% col.0 FILTER uri %]">Link</a>'
+ },
+ [% END %]
+ ];
+ [% END %]
+-->
+</script>
+
+<h3>[% terms.Bug %] counts per component, version and milestone.</h3>
+
+<p>
+ <a href="#component">Component</a> |
+ <a href="#version">Version</a> |
+ <a href="#milestone">Milestone</a>
+</p>
+
+<p>Click on a value to show a list of most recently updated [% terms.bugs %].</p>
+
+<div class="yui3-skin-sam">
+ <a name="component"></a>
+ <b>Component</b>
+ <div id="component_counts"></div>
+ <br>
+ <a name="version"></a>
+ <b>Version</b>
+ (<a href="#top">back to top</a>)
+ <div id="version_counts"></div>
+ [% IF Param('usetargetmilestone') %]
+ <br>
+ <a name="milestone"></a>
+ <b>Milestone</b>
+ (<a href="#top">back to top</a>)
+ <div id="milestone_counts"></div>
+ [% END %]
+</div>
+
+[% END %]
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/duplicates.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/duplicates.html.tmpl
new file mode 100644
index 000000000..585cdc829
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/duplicates.html.tmpl
@@ -0,0 +1,34 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<script type="text/javascript">
+ PD.duplicates = [
+ [% FOREACH bug = by_duplicate %]
+ {
+ id: '[% bug.id FILTER js %]',
+ count: '[% bug.dupe_count FILTER js %]',
+ status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+</script>
+
+<h3>Most duplicated [% terms.bugs %]</h3>
+
+[% IF by_duplicate.size %]
+ <b>[% by_duplicate.size FILTER html %]&nbsp;[% terms.Bugs %] Found</b>
+ <div class="yui3-skin-sam">
+ <div id="duplicates"></div>
+ </div>
+[% ELSE %]
+ <b>No duplicate [% terms.bugs %] found.</b>
+[% END %]
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/popularity.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/popularity.html.tmpl
new file mode 100644
index 000000000..933f26c81
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/popularity.html.tmpl
@@ -0,0 +1,38 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<style>
+ .yui-skin-sam .yui-dt table {width:100%;}
+</style>
+
+<script type="text/javascript">
+ PD.popularity = [
+ [% FOREACH bug = by_popularity %]
+ {
+ id: '[% bug.id FILTER js %]',
+ count: '[% bug.votes FILTER js %]',
+ status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+</script>
+
+<h3>Most voted on [% terms.bugs %]</h3>
+
+[% IF by_popularity.size %]
+ <b>[% by_popularity.size FILTER html %]&nbsp;[% terms.Bugs %] Found</b>
+ <div class="yui3-skin-sam">
+ <div id="popularity"></div>
+ </div>
+[% ELSE %]
+ <b>No [% terms.bugs %] found.</b>
+[% END %]
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/recents.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/recents.html.tmpl
new file mode 100644
index 000000000..66320e174
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/recents.html.tmpl
@@ -0,0 +1,87 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<script type="text/javascript">
+ PD.recents = {};
+
+ // Recently opened
+ PD.recents.opened = [
+ [% FOREACH bug = recently_opened %]
+ {
+ id: '[% bug.id FILTER js %]',
+ status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+
+ // Recently closed
+ PD.recents.closed = [
+ [% FOREACH bug = recently_closed %]
+ {
+ id: '[% bug.id FILTER js %]',
+ status: '[% bug.status FILTER js %]',
+ version: '[% bug.version FILTER js %]',
+ component: '[% bug.component FILTER js %]',
+ severity: '[% bug.severity FILTER js %]',
+ summary: '[% bug.summary FILTER js %]'
+ },
+ [% END %]
+ ];
+</script>
+
+<h3>Most recently opened and closed [% terms.bugs %]</h3>
+
+<p>
+ Activity within the last <input type="text" size="4" name="recent_days"
+ value="[% recent_days FILTER html %]">
+ days (between 1 and 100) or from
+ <input name="date_from" size="10" id="date_from"
+ value="[% date_from FILTER html %]"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_date_from"
+ onclick="showCalendar('date_from')">
+ <span>Calendar</span>
+ </button>
+ <span id="con_calendar_date_from"></span>
+ to
+ <input name="date_to" size="10" id="date_to"
+ value="[% date_to FILTER html %]"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button"
+ id="button_calendar_date_to"
+ onclick="showCalendar('date_to')">
+ <span>Calendar</span>
+ </button>
+ <span id="con_calendar_date_to"></span>
+ <script type="text/javascript">
+ createCalendar('date_from')
+ createCalendar('date_to')
+ </script>
+ <input type="submit" name="change" value="Change">
+</p>
+<p>
+ <a href="#recently_opened">Recently Opened</a>
+ <span class="separator"> | </span>
+ <a href="#recently_closed">Recently Closed</a>
+</p>
+
+<div class="yui-skin-sam">
+ <a name="recently_opened"></a>
+ <b>[% recently_opened.size FILTER html %] Recently Opened [% terms.Bugs %]</b>
+ <div id="recently_opened"></div>
+ <br>
+ <a name="recently_closed"></a>
+ <b>[% recently_closed.size FILTER html %] Recently Closed [% terms.Bugs %]</b>
+ (<a href="#top">back to top</a>)
+ <div id="recently_closed"></div>
+</div>
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/roadmap.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/roadmap.html.tmpl
new file mode 100644
index 000000000..b31827fbd
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/roadmap.html.tmpl
@@ -0,0 +1,27 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<script type="text/javascript">
+<!--
+ PD.roadmap = [
+ [% FOREACH milestone = by_roadmap %]
+ {
+ name: '[% milestone.name FILTER js %]',
+ percentage: '[% milestone.percentage FILTER js %]',
+ link: '<a href="[% milestone.link_closed FILTER html %]">[% milestone.closed_bugs FILTER html %]</a> of <a href="[% milestone.link_total FILTER html %]"> [% milestone.total_bugs FILTER html %]</a> [% terms.bugs %] have been closed',
+ },
+ [% END %]
+ ];
+-->
+</script>
+
+<h3>Percentage of [% terms.bug %] closure per milestone</h3>
+
+<div class="yui3-skin-sam">
+ <div id="bug_milestones"></div>
+</div>
diff --git a/extensions/ProductDashboard/template/en/default/pages/productdashboard/summary.html.tmpl b/extensions/ProductDashboard/template/en/default/pages/productdashboard/summary.html.tmpl
new file mode 100644
index 000000000..30b6f3dca
--- /dev/null
+++ b/extensions/ProductDashboard/template/en/default/pages/productdashboard/summary.html.tmpl
@@ -0,0 +1,122 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+<script>
+ PD.summary = {};
+
+ // global counts
+ PD.summary.bug_counts = [
+ {
+ name: "Total [% terms.Bugs %]",
+ count: [% total_bugs || 0 FILTER js %],
+ percentage: [% total_bugs ? "100" : "0" %],
+ link: '<a href="[% bug_link_all FILTER js %]">Link</a>',
+ },
+ {
+ name: "Open [% terms.Bugs %]",
+ count: [% total_open_bugs || 0 FILTER js %],
+ percentage: [% open_bugs_percentage FILTER js %],
+ link: '<a href="[% bug_link_open FILTER js %]">Link</a>',
+ },
+ {
+ name: "Closed [% terms.Bugs %]",
+ count: [% total_closed_bugs || 0 FILTER js %],
+ percentage: [% closed_bugs_percentage FILTER js %],
+ link: '<a href="[% bug_link_closed FILTER js %]">Link</a>',
+ }
+ ];
+
+ // Status counts
+ PD.summary.status_counts = [
+ [% FOREACH col = by_status %]
+ [% NEXT IF col.0 == 'CLOSED' %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link_all FILTER js %]&amp;bug_status=[% col.0 FILTER uri FILTER js %]">Link</a>'
+ },
+ [% END %]
+ ];
+
+ // Priority counts
+ PD.summary.priority_counts = [
+ [% FOREACH col = by_priority %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link FILTER js %]&amp;priority=[% col.0 FILTER uri FILTER js %]">Link</a>'
+ },
+ [% END %]
+ ];
+
+ // Severity counts
+ PD.summary.severity_counts = [
+ [% FOREACH col = by_severity %]
+ {
+ name: "[% col.0 FILTER js %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '<a href="[% bug_link FILTER js %]&amp;bug_severity=[% col.0 FILTER uri FILTER js %]">Link</a>'
+ },
+ [% END %]
+ ];
+
+ // Assignee counts
+ PD.summary.assignee_counts = [
+ [% FOREACH col = by_assignee %]
+ {
+ name: "[% IF user.id %][% col.0.email FILTER js %][% ELSE %][% col.0.realname || 'No Name' FILTER js %][% END %]",
+ count: [% col.1 || 0 FILTER js %],
+ percentage: [% col.2 || 0 FILTER js %],
+ link: '[% IF user.id %]<a href="[% bug_link FILTER js %]&amp;emailassigned_to1=1&amp;emailtype1=exact&amp;email1=[% col.0.email FILTER uri FILTER js %]">Link</a>[% END %]'
+ },
+ [% END %]
+ ];
+</script>
+
+<h3>Summary of [% terms.bug %] counts</h3>
+
+<p>
+ <a href="#counts">Counts</a>
+ <span class="separator"> | </span>
+ <a href="#status">Status</a>
+ <span class="separator"> | </span>
+ <a href="#priority">Priority</a>
+ <span class="separator"> | </span>
+ <a href="#severity">Severity</a>
+ <span class="separator"> | </span>
+ <a href="#assignee">Assignee</a>
+</p>
+
+<div class="yui3-skin-sam">
+ <a name="counts"></a>
+ <b>[% terms.Bug %] Counts</b>
+ <div id="bug_counts"></div>
+ <br>
+ <a name="status"></a>
+ <b>Status</b>
+ (<a href="#top">back to top</a>)
+ <div id="status_counts"></div>
+ <br>
+ <a name="priority"></a>
+ <b>Priority</b>
+ (<a href="#top">back to top</a>)
+ <div id="priority_counts"></div>
+ <br>
+ <a name="severity"></a>
+ <b>Severity</b>
+ (<a href="#top">back to top</a>)
+ <div id="severity_counts"></div>
+ <br>
+ <a name="assignee"></a>
+ <b>Assignee</b>
+ (<a href="#top">back to top</a>)
+ <div id="assignee_counts"></div>
+</div>
diff --git a/extensions/ProductDashboard/web/images/spacer.gif b/extensions/ProductDashboard/web/images/spacer.gif
new file mode 100644
index 000000000..fc2560981
--- /dev/null
+++ b/extensions/ProductDashboard/web/images/spacer.gif
Binary files differ
diff --git a/extensions/ProductDashboard/web/js/components.js b/extensions/ProductDashboard/web/js/components.js
new file mode 100644
index 000000000..538b15457
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/components.js
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function(Y) {
+ if (typeof PD.updated_recently != 'undefined') {
+ var columns = [
+ { key:"id", label:"ID", sortable:true, allowHTML: true,
+ formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>' },
+ { key:"bug_status", label:"Status", sortable:true },
+ { key:"version", label:"Version", sortable:true },
+ { key:"component", label:"Component", sortable:true },
+ { key:"severity", label:"Severity", sortable:true },
+ { key:"summary", label:"Summary", sortable:false },
+ ];
+
+ var updatedRecentlyDataTable = new Y.DataTable({
+ columns: columns,
+ data: PD.updated_recently
+ });
+ updatedRecentlyDataTable.render("#updated_recently");
+
+ if (typeof PD.past_due != 'undefined') {
+ var pastDueDataTable = new Y.DataTable({
+ columns: columns,
+ data: PD.past_due
+ });
+ pastDueDataTable.render('#past_due');
+ }
+ }
+
+ if (typeof PD.component_counts != 'undefined') {
+ var summary_url = '<a href="page.cgi?id=productdashboard.html&amp;product=' +
+ encodeURIComponent(PD.product_name) + '&bug_status=' +
+ encodeURIComponent(PD.bug_status) + '&tab=components';
+
+ var columns = [
+ { key:"name", label:"Name", sortable:true, allowHTML: true,
+ formatter: summary_url + '&component={value}">{value}</a>' },
+ { key:"count", label:"Count", sortable:true },
+ { key:"percentage", label:"Percentage", sortable:false, allowHTML: true,
+ formatter: '<div class="percentage"><div class="bar" style="width:{value}%"></div><div class="percent">{value}%</div></div>' },
+ { key:"link", label:"Link", sortable:false, allowHTML: true }
+ ];
+
+ var componentsDataTable = new Y.DataTable({
+ columns: columns,
+ data: PD.component_counts
+ });
+ componentsDataTable.render("#component_counts");
+
+ columns[0].formatter = summary_url + '&version={value}">{value}</a>';
+ var versionsDataTable = new Y.DataTable({
+ columns: columns,
+ data: PD.version_counts
+ });
+ versionsDataTable.render('#version_counts');
+
+ if (typeof PD.milestone_counts != 'undefined') {
+ columns[0].formatter = summary_url + '&target_milestone={value}">{value}</a>';
+ var milestonesDataTable = new Y.DataTable({
+ columns: columns,
+ data: PD.milestone_counts
+ });
+ milestonesDataTable.render('#milestone_counts');
+ }
+ }
+});
diff --git a/extensions/ProductDashboard/web/js/duplicates.js b/extensions/ProductDashboard/web/js/duplicates.js
new file mode 100644
index 000000000..5e3193a65
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/duplicates.js
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function (Y) {
+ var column_defs = [
+ { key:"id", label:"ID", sortable:true, allowHTML: true,
+ formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>' },
+ { key:"count", label:"Count", sortable:true },
+ { key:"status", label:"Status", sortable:true },
+ { key:"version", label:"Version", sortable:true },
+ { key:"component", label:"Component", sortable:true },
+ { key:"severity", label:"Severity", sortable:true },
+ { key:"summary", label:"Summary", sortable:false },
+ ];
+
+ var duplicatesDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.duplicates
+ }).render('#duplicates');
+});
diff --git a/extensions/ProductDashboard/web/js/popularity.js b/extensions/ProductDashboard/web/js/popularity.js
new file mode 100644
index 000000000..b78b67867
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/popularity.js
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function (Y) {
+ var column_defs = [
+ { key:"id", label:"ID", sortable:true, allowHTML: true,
+ formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>' },
+ { key:"count", label:"Count", sortable:true },
+ { key:"status", label:"Status", sortable:true },
+ { key:"version", label:"Version", sortable:true },
+ { key:"component", label:"Component", sortable:true },
+ { key:"severity", label:"Severity", sortable:true },
+ { key:"summary", label:"Summary", sortable:false },
+ ];
+
+ var popularityDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.popularity
+ }).render('#popularity');
+});
diff --git a/extensions/ProductDashboard/web/js/recents.js b/extensions/ProductDashboard/web/js/recents.js
new file mode 100644
index 000000000..84e1758b6
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/recents.js
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function (Y) {
+ var column_defs = [
+ { key:"id", label:"ID", sortable:true, allowHTML: true,
+ formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>' },
+ { key:"status", label:"Status", sortable:true },
+ { key:"version", label:"Version", sortable:true },
+ { key:"component", label:"Component", sortable:true },
+ { key:"severity", label:"Severity", sortable:true },
+ { key:"summary", label:"Summary", sortable:false },
+ ];
+
+ var recentlyOpenedDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.recents.opened
+ }).render('#recently_opened');
+
+ var recentlyClosedDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.recents.closed
+ }).render('#recently_closed');
+});
diff --git a/extensions/ProductDashboard/web/js/roadmap.js b/extensions/ProductDashboard/web/js/roadmap.js
new file mode 100644
index 000000000..1bef5b091
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/roadmap.js
@@ -0,0 +1,24 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function (Y) {
+ var column_defs = [
+ { key: 'name', label: 'Name', sortable: true },
+ { key: 'percentage', label: 'Percentage', sortable: false, allowHTML: true,
+ formatter: '<div class="percentage"><div class="bar" style="width:{value}%"></div><div class="percent">{value}%</div></div>' },
+ { key: 'link', label: 'Links', allowHTML: true, sortable: false }
+ ];
+
+ var roadmapDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.roadmap,
+ }).render('#bug_milestones');
+});
diff --git a/extensions/ProductDashboard/web/js/summary.js b/extensions/ProductDashboard/web/js/summary.js
new file mode 100644
index 000000000..59d000d7b
--- /dev/null
+++ b/extensions/ProductDashboard/web/js/summary.js
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+YUI({
+ base: 'js/yui3/',
+ combine: false
+}).use("datatable", "datatable-sort", function (Y) {
+ var column_defs = [
+ { key: 'name', label: 'Name', sortable: true },
+ { key: 'count', label: 'Count', sortable: true },
+ { key: 'percentage', label: 'Percentage', sortable: true, allowHTML: true,
+ formatter: '<div class="percentage"><div class="bar" style="width:{value}%"></div><div class="percent">{value}%</div></div>' },
+ { key: 'link', label: 'Link', allowHTML: true }
+ ];
+
+ var bugsCountDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.summary.bug_counts
+ }).render('#bug_counts');
+
+ var statusCountsDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.summary.status_counts
+ }).render('#status_counts');
+
+ var priorityCountsDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.summary.priority_counts
+ }).render('#priority_counts');
+
+ var severityCountsDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.summary.severity_counts
+ }).render('#severity_counts');
+
+ var assigneeCountsDataTable = new Y.DataTable({
+ columns: column_defs,
+ data: PD.summary.assignee_counts
+ }).render('#assignee_counts');
+});
diff --git a/extensions/ProductDashboard/web/styles/productdashboard.css b/extensions/ProductDashboard/web/styles/productdashboard.css
new file mode 100644
index 000000000..c0c45cf38
--- /dev/null
+++ b/extensions/ProductDashboard/web/styles/productdashboard.css
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#product_dashboard_links {
+ float: right;
+ padding-right: 25px;
+ border: 1px solid rgb(116, 126, 147);
+}
+
+.product_name {
+ font-size: 2em;
+ margin: 10px 0 10px 0;
+ color: rgb(109, 117, 129);
+}
+
+.product_description {
+ font-size: 90%;
+ font-style: italic;
+ padding-bottom: 5px;
+ margin-bottom: 10px;
+}
+
+.percentage {
+ position:relative;
+ width: 200px;
+ border: 1px solid rgb(203, 203, 203);
+ position: relative;
+ padding: 3px;
+}
+
+.bar{
+ background-color: #00ff00;
+ height: 20px;
+}
+
+.percent{
+ position: absolute;
+ display: inline-block;
+ top: 3px;
+ left: 48%;
+}
diff --git a/extensions/Profanivore/Config.pm b/extensions/Profanivore/Config.pm
new file mode 100644
index 000000000..354325c58
--- /dev/null
+++ b/extensions/Profanivore/Config.pm
@@ -0,0 +1,40 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Profanivore Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::Profanivore;
+use strict;
+
+use constant NAME => 'Profanivore';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'Regexp-Common',
+ module => 'Regexp::Common',
+ version => 0
+ },
+ {
+ package => 'HTML-Tree',
+ module => 'HTML::Tree',
+ version => 0,
+ }
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/Profanivore/Extension.pm b/extensions/Profanivore/Extension.pm
new file mode 100644
index 000000000..cdec6e1c6
--- /dev/null
+++ b/extensions/Profanivore/Extension.pm
@@ -0,0 +1,169 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Profanivore Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::Profanivore;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Regexp::Common 'RE_ALL';
+
+use Bugzilla::Util qw(is_7bit_clean);
+
+our $VERSION = '0.01';
+
+sub bug_format_comment {
+ my ($self, $args) = @_;
+ my $regexes = $args->{'regexes'};
+ my $comment = $args->{'comment'};
+
+ # Censor profanities if the comment author is not reasonably trusted.
+ # However, allow people to see their own profanities, which might stop
+ # them immediately noticing and trying to go around the filter. (I.e.
+ # it tries to stop an arms race starting.)
+ if ($comment &&
+ !$comment->author->in_group('editbugs') &&
+ $comment->author->id != Bugzilla->user->id)
+ {
+ push (@$regexes, {
+ match => RE_profanity('-i'),
+ replace => \&_replace_profanity
+ });
+ }
+}
+
+sub _replace_profanity {
+ # We don't have access to the actual profanity.
+ return "****";
+}
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+ my $email = $args->{'email'};
+
+ my $author = $email->header("X-Bugzilla-Who");
+ my $recipient = $email->header("To");
+
+ if ($author && $recipient && lc($author) ne lc($recipient)) {
+ my $email_suffix = Bugzilla->params->{'emailsuffix'};
+ if ($email_suffix ne '') {
+ $recipient =~ s/\Q$email_suffix\E$//;
+ $author =~ s/\Q$email_suffix\E$//;
+ }
+
+ $author = new Bugzilla::User({ name => $author });
+
+ if ($author &&
+ $author->id &&
+ !$author->in_group('editbugs'))
+ {
+ # Multipart emails
+ if (scalar $email->parts > 1) {
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ return if $part->parts > 1; # Top-level
+ # do not filter attachments such as patches, etc.
+ if ($part->header('Content-Disposition')
+ && $part->header('Content-Disposition') =~ /attachment/)
+ {
+ return;
+ }
+ _fix_encoding($part);
+ my $body = $part->body_str;
+ my $new_body;
+ if ($part->content_type =~ /^text\/html/) {
+ $new_body = _filter_html($body);
+ if ($new_body ne $body) {
+ # HTML::Tree removes unnecessary whitespace,
+ # resulting in very long lines. We need to use
+ # quoted-printable encoding to avoid exceeding
+ # email's maximum line length.
+ $part->encoding_set('quoted-printable');
+ }
+ }
+ elsif ($part->content_type =~ /^text\/plain/) {
+ $new_body = _filter_text($body);
+ }
+ if ($new_body && $new_body ne $body) {
+ $part->body_str_set($new_body);
+ }
+ });
+ }
+ # Single part email
+ else {
+ _fix_encoding($email);
+ $email->body_str_set(_filter_text($email->body_str));
+ }
+ }
+ }
+}
+
+sub _fix_encoding {
+ my $part = shift;
+ my $body = $part->body;
+ if (Bugzilla->params->{'utf8'}) {
+ $part->charset_set('UTF-8');
+ # encoding_set works only with bytes, not with utf8 strings.
+ my $raw = $part->body_raw;
+ if (utf8::is_utf8($raw)) {
+ utf8::encode($raw);
+ $part->body_set($raw);
+ }
+ }
+ $part->encoding_set('quoted-printable') if !is_7bit_clean($body);
+}
+
+sub _filter_text {
+ my $text = shift;
+ my $offensive = RE_profanity('-i');
+ $text =~ s/$offensive/****/g;
+ return $text;
+}
+
+sub _filter_html {
+ my $html = shift;
+ my $tree = HTML::Tree->new->parse_content($html);
+ my $comments_div = $tree->look_down( _tag => 'div', id => 'comments' );
+ return $html if !$comments_div;
+ my @comments = $comments_div->look_down( _tag => 'pre' );
+ my $dirty = 0;
+ foreach my $comment (@comments) {
+ _filter_html_node($comment, \$dirty);
+ }
+ return $dirty ? $tree->as_HTML : $html;
+}
+
+sub _filter_html_node {
+ my ($node, $dirty) = @_;
+ my $content = [ $node->content_list ];
+ foreach my $item_r ($node->content_refs_list) {
+ if (ref $$item_r) {
+ _filter_html_node($$item_r);
+ } else {
+ my $new_text = _filter_text($$item_r);
+ if ($new_text ne $$item_r) {
+ $$item_r = $new_text;
+ $$dirty = 1;
+ }
+ }
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Profanivore/README b/extensions/Profanivore/README
new file mode 100644
index 000000000..5ccab103f
--- /dev/null
+++ b/extensions/Profanivore/README
@@ -0,0 +1,14 @@
+Profanivore 'eats' English profanities in comments, leaving behind instead a
+trail of droppings ('****'). It finds its food using a standard library Perl
+regexp. The profanity is only eaten where the comment was written by a user
+who does not have the global 'editbugs' privilege. The digestion happens at
+display time, so the comment in the database is unaltered.
+
+However, it does not eat profanities when showing people their own comments;
+the aim here is to prevent people immediately noticing they are being
+censored, and getting 'creative'.
+
+The purpose of Profanivore is to make it a little harder for trolls to
+vandalise public Bugzilla installations.
+
+It does not currently affect fields other than comments.
diff --git a/extensions/Push/Config.pm b/extensions/Push/Config.pm
new file mode 100644
index 000000000..45cae9183
--- /dev/null
+++ b/extensions/Push/Config.pm
@@ -0,0 +1,61 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push;
+
+use strict;
+
+use constant NAME => 'Push';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'Daemon-Generic',
+ module => 'Daemon::Generic',
+ version => '0'
+ },
+ {
+ package => 'JSON-XS',
+ module => 'JSON::XS',
+ version => '2.0'
+ },
+ {
+ package => 'Crypt-CBC',
+ module => 'Crypt::CBC',
+ version => '0'
+ },
+ {
+ package => 'Crypt-DES',
+ module => 'Crypt::DES',
+ version => '0'
+ },
+ {
+ package => 'Crypt-DES_EDE3',
+ module => 'Crypt::DES_EDE3',
+ version => '0'
+ },
+];
+
+use constant OPTIONAL_MODULES => [
+ # connectors need the ability to extend this
+ {
+ package => 'Net--RabbitMQ',
+ module => 'Net::RabbitMQ',
+ version => '0'
+ },
+ {
+ package => 'Net-SFTP',
+ module => 'Net::SFTP',
+ version => '0'
+ },
+ {
+ package => 'XML-Simple',
+ module => 'XML::Simple',
+ version => '0'
+ },
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/Push/Extension.pm b/extensions/Push/Extension.pm
new file mode 100644
index 000000000..ff7f21295
--- /dev/null
+++ b/extensions/Push/Extension.pm
@@ -0,0 +1,645 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Constants;
+use Bugzilla::Comment;
+use Bugzilla::Error;
+use Bugzilla::Extension::Push::Admin;
+use Bugzilla::Extension::Push::Connectors;
+use Bugzilla::Extension::Push::Logger;
+use Bugzilla::Extension::Push::Message;
+use Bugzilla::Extension::Push::Push;
+use Bugzilla::Extension::Push::Serialise;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Install::Filesystem;
+
+use Encode;
+use Scalar::Util 'blessed';
+use Storable 'dclone';
+
+our $VERSION = '1';
+
+$Carp::CarpInternal{'CGI::Carp'} = 1;
+
+#
+# monkey patch for convience
+#
+
+BEGIN {
+ *Bugzilla::push_ext = \&_get_instance;
+}
+
+sub _get_instance {
+ my $cache = Bugzilla->request_cache;
+ if (!$cache->{'push.instance'}) {
+ my $instance = Bugzilla::Extension::Push::Push->new();
+ $cache->{'push.instance'} = $instance;
+ $instance->logger(Bugzilla::Extension::Push::Logger->new());
+ $instance->connectors(Bugzilla::Extension::Push::Connectors->new());
+ }
+ return $cache->{'push.instance'};
+}
+
+#
+# enabled
+#
+
+sub _enabled {
+ my ($self) = @_;
+ if (!exists $self->{'enabled'}) {
+ my $push = Bugzilla->push_ext;
+ $self->{'enabled'} = $push->config->{enabled} eq 'Enabled';
+ if ($self->{'enabled'}) {
+ # if no connectors are enabled, no need to push anything
+ $self->{'enabled'} = 0;
+ foreach my $connector (Bugzilla->push_ext->connectors->list) {
+ if ($connector->enabled) {
+ $self->{'enabled'} = 1;
+ last;
+ }
+ }
+ }
+ }
+ return $self->{'enabled'};
+}
+
+#
+# deal with creation and updated events
+#
+
+sub _object_created {
+ my ($self, $args) = @_;
+
+ my $object = _get_object_from_args($args);
+ return unless $object;
+ return unless _should_push($object);
+
+ $self->_push_object('create', $object, change_set_id(), { timestamp => $args->{'timestamp'} });
+}
+
+sub _object_modified {
+ my ($self, $args) = @_;
+
+ my $object = _get_object_from_args($args);
+ return unless $object;
+ return unless _should_push($object);
+
+ my $changes = $args->{'changes'} || {};
+ return unless scalar keys %$changes;
+
+ my $change_set = change_set_id();
+
+ # detect when a bug changes from public to private (or back), so connectors
+ # can remove now-private bugs if required.
+ if ($object->isa('Bugzilla::Bug')) {
+ # we can't use user->can_see_bug(old_bug) as that works on IDs, and the
+ # bug has already been updated, so for now assume that a bug without
+ # groups is public.
+ my $old_bug = $args->{'old_bug'};
+ my $is_public = is_public($object);
+ my $was_public = $old_bug ? !@{$old_bug->groups_in} : $is_public;
+
+ if (!$is_public && $was_public) {
+ # bug is changing from public to private
+ # push a fake update with the just is_private change
+ my $private_changes = {
+ timestamp => $args->{'timestamp'},
+ changes => [
+ {
+ field => 'is_private',
+ removed => '0',
+ added => '1',
+ },
+ ],
+ };
+ # note we're sending the old bug object so we don't leak any
+ # security sensitive information.
+ $self->_push_object('modify', $old_bug, $change_set, $private_changes);
+ } elsif ($is_public && !$was_public) {
+ # bug is changing from private to public
+ # push a fake update with the just is_private change
+ my $private_changes = {
+ timestamp => $args->{'timestamp'},
+ changes => [
+ {
+ field => 'is_private',
+ removed => '1',
+ added => '0',
+ },
+ ],
+ };
+ # it's ok to send the new bug state here
+ $self->_push_object('modify', $object, $change_set, $private_changes);
+ }
+ }
+
+ # make flagtypes changes easier to process
+ if (exists $changes->{'flagtypes.name'}) {
+ _split_flagtypes($changes);
+ }
+
+ # TODO split group changes?
+
+ # restructure the changes hash
+ my $changes_data = {
+ timestamp => $args->{'timestamp'},
+ changes => [],
+ };
+ foreach my $field_name (sort keys %$changes) {
+ push @{$changes_data->{'changes'}}, {
+ field => $field_name,
+ removed => $changes->{$field_name}[0],
+ added => $changes->{$field_name}[1],
+ };
+ }
+
+ $self->_push_object('modify', $object, $change_set, $changes_data);
+}
+
+sub _get_object_from_args {
+ my ($args) = @_;
+ return get_first_value($args, qw(object bug flag group));
+}
+
+sub _should_push {
+ my ($object_or_class) = @_;
+ my $class = blessed($object_or_class) || $object_or_class;
+ return grep { $_ eq $class } qw(Bugzilla::Bug Bugzilla::Attachment Bugzilla::Comment);
+}
+
+# changes to bug flags are presented in a single field 'flagtypes.name' split
+# into individual fields
+sub _split_flagtypes {
+ my ($changes) = @_;
+
+ my @removed = _split_flagtype($changes->{'flagtypes.name'}->[0]);
+ my @added = _split_flagtype($changes->{'flagtypes.name'}->[1]);
+ delete $changes->{'flagtypes.name'};
+
+ foreach my $ra (@removed, @added) {
+ $changes->{$ra->[0]} = ['', ''];
+ }
+ foreach my $ra (@removed) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[0] = $value;
+ }
+ foreach my $ra (@added) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[1] = $value;
+ }
+}
+
+sub _split_flagtype {
+ my ($value) = @_;
+ my @result;
+ foreach my $change (split(/, /, $value)) {
+ my $requestee = '';
+ if ($change =~ s/\(([^\)]+)\)$//) {
+ $requestee = $1;
+ }
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+ $value .= " ($requestee)" if $requestee;
+ push @result, [ "flag.$name", $value ];
+ }
+ return @result;
+}
+
+# changes to attachment flags come in via flag_end_of_update which has a
+# completely different structure for reporting changes than
+# object_end_of_update. this morphs flag to object updates.
+sub _morph_flag_updates {
+ my ($args) = @_;
+
+ my @removed = _morph_flag_update($args->{'old_flags'});
+ my @added = _morph_flag_update($args->{'new_flags'});
+ delete $args->{'old_flags'};
+ delete $args->{'new_flags'};
+
+ my $changes = {};
+ foreach my $ra (@removed, @added) {
+ $changes->{$ra->[0]} = ['', ''];
+ }
+ foreach my $ra (@removed) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[0] = $value;
+ }
+ foreach my $ra (@added) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[1] = $value;
+ }
+
+ foreach my $flag (keys %$changes) {
+ if ($changes->{$flag}->[0] eq $changes->{$flag}->[1]) {
+ delete $changes->{$flag};
+ }
+ }
+
+ $args->{'changes'} = $changes;
+}
+
+sub _morph_flag_update {
+ my ($values) = @_;
+ my @result;
+ foreach my $change (@$values) {
+ $change =~ s/^[^:]+://;
+ my $requestee = '';
+ if ($change =~ s/\(([^\)]+)\)$//) {
+ $requestee = $1;
+ }
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+ $value .= " ($requestee)" if $requestee;
+ push @result, [ "flag.$name", $value ];
+ }
+ return @result;
+}
+
+#
+# serialise and insert into the table
+#
+
+sub _push_object {
+ my ($self, $message_type, $object, $change_set, $changes) = @_;
+ my $rh;
+
+ # serialise the object
+ my ($rh_object, $name) = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($object);
+
+ if (!$rh_object) {
+ warn "empty hash from serialiser ($message_type $object)\n";
+ return;
+ }
+ $rh->{$name} = $rh_object;
+
+ # add in the events hash
+ my $rh_event = Bugzilla::Extension::Push::Serialise->instance->changes_to_event($changes);
+ return unless $rh_event;
+ $rh_event->{'action'} = $message_type;
+ $rh_event->{'target'} = $name;
+ $rh_event->{'change_set'} = $change_set;
+ $rh_event->{'routing_key'} = "$name.$message_type";
+ if (exists $rh_event->{'changes'}) {
+ $rh_event->{'routing_key'} .= ':' . join(',', map { $_->{'field'} } @{$rh_event->{'changes'}});
+ }
+ $rh->{'event'} = $rh_event;
+
+ # create message object
+ my $message = Bugzilla::Extension::Push::Message->new_transient({
+ payload => to_json($rh),
+ change_set => $change_set,
+ routing_key => $rh_event->{'routing_key'},
+ });
+
+ # don't hit the database unless there are interested connectors
+ my $should_push = 0;
+ foreach my $connector (Bugzilla->push_ext->connectors->list) {
+ next unless $connector->enabled;
+ next unless $connector->should_send($message);
+ $should_push = 1;
+ last;
+ }
+ return unless $should_push;
+
+ # insert into push table
+ $message->create_from_transient();
+}
+
+#
+# update/create hooks
+#
+
+sub object_end_of_create {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+
+ # it's better to process objects from a non-generic end_of_create where
+ # possible; don't process them here to avoid duplicate messages
+ my $object = _get_object_from_args($args);
+ return if !$object ||
+ $object->isa('Bugzilla::Bug') ||
+ blessed($object) =~ /^Bugzilla::Extension/;
+
+ $self->_object_created($args);
+}
+
+sub object_end_of_update {
+ my ($self, $args) = @_;
+
+ # User objects are updated with every page load (to touch the session
+ # token). Because we ignore user objects, there's no need to create an
+ # instance of Push to check if we're enabled.
+ my $object = _get_object_from_args($args);
+ return if !$object || $object->isa('Bugzilla::User');
+
+ return unless $self->_enabled;
+
+ # it's better to process objects from a non-generic end_of_update where
+ # possible; don't process them here to avoid duplicate messages
+ return if $object->isa('Bugzilla::Bug') ||
+ $object->isa('Bugzilla::Flag') ||
+ blessed($object) =~ /^Bugzilla::Extension/;
+
+ $self->_object_modified($args);
+}
+
+# process bugs once they are fully formed
+# object_end_of_update is triggered while a bug is being created
+sub bug_end_of_create {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ $self->_object_created($args);
+}
+
+sub bug_end_of_update {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ $self->_object_modified($args);
+}
+
+sub flag_end_of_update {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ _morph_flag_updates($args);
+ $self->_object_modified($args);
+}
+
+# comments in bugzilla 4.0 doesn't aren't included in the bug_end_of_* hooks,
+# this code uses custom hooks to trigger
+sub bug_comment_create {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+
+ return unless _should_push('Bugzilla::Comment');
+ my $bug = $args->{'bug'} or return;
+ my $timestamp = $args->{'timestamp'} or return;
+
+ my $comments = Bugzilla::Comment->match({ bug_id => $bug->id, bug_when => $timestamp });
+
+ foreach my $comment (@$comments) {
+ if ($comment->body ne '') {
+ $self->_push_object('create', $comment, change_set_id(), { timestamp => $timestamp });
+ }
+ }
+}
+
+sub bug_comment_update {
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+
+ return unless _should_push('Bugzilla::Comment');
+ my $bug = $args->{'bug'} or return;
+ my $timestamp = $args->{'timestamp'} or return;
+
+ my $comment_id = $args->{'comment_id'};
+ if ($comment_id) {
+ # XXX this should set changes. only is_private changes will trigger this event
+ my $comment = Bugzilla::Comment->new($comment_id);
+ $self->_push_object('update', $comment, change_set_id(), { timestamp => $timestamp });
+
+ } else {
+ # when a bug is created, an update is also triggered; we don't want to sent
+ # update messages for the initial comment, or for empty comments
+ my $comments = Bugzilla::Comment->match({ bug_id => $bug->id, bug_when => $timestamp });
+ foreach my $comment (@$comments) {
+ if ($comment->body ne '' && $comment->count) {
+ $self->_push_object('create', $comment, change_set_id(), { timestamp => $timestamp });
+ }
+ }
+ }
+}
+
+#
+# admin hooks
+#
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ if ($page eq 'push_config.html') {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ { group => 'admin',
+ action => 'access',
+ object => 'administrative_pages' });
+ admin_config($vars);
+
+ } elsif ($page eq 'push_queues.html'
+ || $page eq 'push_queues_view.html'
+ ) {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ { group => 'admin',
+ action => 'access',
+ object => 'administrative_pages' });
+ admin_queues($vars, $page);
+
+ } elsif ($page eq 'push_log.html') {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ { group => 'admin',
+ action => 'access',
+ object => 'administrative_pages' });
+ admin_log($vars);
+ }
+}
+
+#
+# installation/config hooks
+#
+
+sub db_schema_abstract_schema {
+ my ($self, $args) = @_;
+ $args->{'schema'}->{'push'} = {
+ FIELDS => [
+ id => {
+ TYPE => 'MEDIUMSERIAL',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ },
+ push_ts => {
+ TYPE => 'DATETIME',
+ NOTNULL => 1,
+ },
+ payload => {
+ TYPE => 'LONGTEXT',
+ NOTNULL => 1,
+ },
+ change_set => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ routing_key => {
+ TYPE => 'VARCHAR(64)',
+ NOTNULL => 1,
+ },
+ ],
+ };
+ $args->{'schema'}->{'push_backlog'} = {
+ FIELDS => [
+ id => {
+ TYPE => 'MEDIUMSERIAL',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ },
+ message_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ },
+ push_ts => {
+ TYPE => 'DATETIME',
+ NOTNULL => 1,
+ },
+ payload => {
+ TYPE => 'LONGTEXT',
+ NOTNULL => 1,
+ },
+ change_set => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ routing_key => {
+ TYPE => 'VARCHAR(64)',
+ NOTNULL => 1,
+ },
+ connector => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ attempt_ts => {
+ TYPE => 'DATETIME',
+ },
+ attempts => {
+ TYPE => 'INT2',
+ NOTNULL => 1,
+ },
+ last_error => {
+ TYPE => 'MEDIUMTEXT',
+ },
+ ],
+ INDEXES => [
+ push_backlog_idx => {
+ FIELDS => ['message_id', 'connector'],
+ TYPE => 'UNIQUE',
+ },
+ ],
+ };
+ $args->{'schema'}->{'push_backoff'} = {
+ FIELDS => [
+ id => {
+ TYPE => 'MEDIUMSERIAL',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ },
+ connector => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ next_attempt_ts => {
+ TYPE => 'DATETIME',
+ },
+ attempts => {
+ TYPE => 'INT2',
+ NOTNULL => 1,
+ },
+ ],
+ INDEXES => [
+ push_backoff_idx => {
+ FIELDS => ['connector'],
+ TYPE => 'UNIQUE',
+ },
+ ],
+ };
+ $args->{'schema'}->{'push_options'} = {
+ FIELDS => [
+ id => {
+ TYPE => 'MEDIUMSERIAL',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ },
+ connector => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ option_name => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ option_value => {
+ TYPE => 'VARCHAR(255)',
+ NOTNULL => 1,
+ },
+ ],
+ INDEXES => [
+ push_options_idx => {
+ FIELDS => ['connector', 'option_name'],
+ TYPE => 'UNIQUE',
+ },
+ ],
+ };
+ $args->{'schema'}->{'push_log'} = {
+ FIELDS => [
+ id => {
+ TYPE => 'MEDIUMSERIAL',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ },
+ message_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ },
+ change_set => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ routing_key => {
+ TYPE => 'VARCHAR(64)',
+ NOTNULL => 1,
+ },
+ connector => {
+ TYPE => 'VARCHAR(32)',
+ NOTNULL => 1,
+ },
+ push_ts => {
+ TYPE => 'DATETIME',
+ NOTNULL => 1,
+ },
+ processed_ts => {
+ TYPE => 'DATETIME',
+ NOTNULL => 1,
+ },
+ result => {
+ TYPE => 'INT1',
+ NOTNULL => 1,
+ },
+ data => {
+ TYPE => 'MEDIUMTEXT',
+ },
+ ],
+ };
+}
+
+sub install_filesystem {
+ my ($self, $args) = @_;
+ my $files = $args->{'files'};
+
+ my $extensionsdir = bz_locations()->{'extensionsdir'};
+ my $scriptname = $extensionsdir . "/Push/bin/bugzilla-pushd.pl";
+
+ $files->{$scriptname} = {
+ perms => Bugzilla::Install::Filesystem::WS_EXECUTE
+ };
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Push/bin/bugzilla-pushd.pl b/extensions/Push/bin/bugzilla-pushd.pl
new file mode 100755
index 000000000..f048df157
--- /dev/null
+++ b/extensions/Push/bin/bugzilla-pushd.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+use warnings;
+
+use FindBin '$RealBin';
+use lib "$RealBin/../../..";
+use lib "$RealBin/../../../lib";
+use lib "$RealBin/../lib";
+
+BEGIN {
+ use Bugzilla;
+ Bugzilla->extensions;
+}
+
+use Bugzilla::Extension::Push::Daemon;
+Bugzilla::Extension::Push::Daemon->start();
+
+=head1 NAME
+
+bugzilla-push.pl - Pushes changes queued by the Push extension to connectors.
+
+=head1 SYNOPSIS
+
+ bugzilla-push.pl [OPTIONS] COMMAND
+
+ OPTIONS:
+ -f Run in the foreground (don't detach)
+ -d Output a lot of debugging information
+ -p file Specify the file where bugzilla-push.pl should store its current
+ process id. Defaults to F<data/bugzilla-push.pl.pid>.
+ -n name What should this process call itself in the system log?
+ Defaults to the full path you used to invoke the script.
+
+ COMMANDS:
+ start Starts a new bugzilla-push daemon if there isn't one running already
+ stop Stops a running bugzilla-push daemon
+ restart Stops a running bugzilla-push if one is running, and then
+ starts a new one.
+ check Report the current status of the daemon.
+ install On some *nix systems, this automatically installs and
+ configures bugzilla-push.pl as a system service so that it will
+ start every time the machine boots.
+ uninstall Removes the system service for bugzilla-push.pl.
+ help Display this usage info
+
+
diff --git a/extensions/Push/bin/nagios_push_checker.pl b/extensions/Push/bin/nagios_push_checker.pl
new file mode 100755
index 000000000..f022f584d
--- /dev/null
+++ b/extensions/Push/bin/nagios_push_checker.pl
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use strict;
+use warnings;
+
+use FindBin '$RealBin';
+use lib "$RealBin/../../..";
+use lib "$RealBin/../../../lib";
+use lib "$RealBin/../lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+# Number of jobs required in the queue before we alert
+
+use constant WARN_COUNT => 500;
+use constant ALARM_COUNT => 750;
+
+use constant NAGIOS_OK => 0;
+use constant NAGIOS_WARNING => 1;
+use constant NAGIOS_CRITICAL => 2;
+
+my $connector = shift
+ || die "Syntax: $0 connector\neg. $0 TCL\n";
+$connector = uc($connector);
+
+my $sql = <<EOF;
+ SELECT COUNT(*)
+ FROM push_backlog
+ WHERE connector = ?
+EOF
+
+my $dbh = Bugzilla->switch_to_shadow_db;
+my ($count) = @{ $dbh->selectcol_arrayref($sql, undef, $connector) };
+
+if ($count < WARN_COUNT) {
+ print "push $connector OK: $count messages found.\n";
+ exit NAGIOS_OK;
+} elsif ($count < ALARM_COUNT) {
+ print "push $connector WARNING: $count messages found.\n";
+ exit NAGIOS_WARNING;
+} else {
+ print "push $connector CRITICAL: $count messages found.\n";
+ exit NAGIOS_CRITICAL;
+}
diff --git a/extensions/Push/lib/Admin.pm b/extensions/Push/lib/Admin.pm
new file mode 100644
index 000000000..f579409bd
--- /dev/null
+++ b/extensions/Push/lib/Admin.pm
@@ -0,0 +1,122 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Admin;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Error;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Util qw(trim detaint_natural trick_taint);
+
+use base qw(Exporter);
+our @EXPORT = qw(
+ admin_config
+ admin_queues
+ admin_log
+);
+
+sub admin_config {
+ my ($vars) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
+
+ if ($input->{save}) {
+ my $dbh = Bugzilla->dbh;
+ $dbh->bz_start_transaction();
+ _update_config_from_form('global', $push->config);
+ foreach my $connector ($push->connectors->list) {
+ _update_config_from_form($connector->name, $connector->config);
+ }
+ $push->set_config_last_modified();
+ $dbh->bz_commit_transaction();
+ $vars->{message} = 'push_config_updated';
+ }
+
+ $vars->{push} = $push;
+ $vars->{connectors} = $push->connectors;
+}
+
+sub _update_config_from_form {
+ my ($name, $config) = @_;
+ my $input = Bugzilla->input_params;
+
+ # read values from form
+ my $values = {};
+ foreach my $option ($config->options) {
+ my $option_name = $option->{name};
+ $values->{$option_name} = trim($input->{$name . ".$option_name"});
+ }
+
+ # validate
+ if ($values->{enabled} eq 'Enabled') {
+ eval {
+ $config->validate($values);
+ };
+ if ($@) {
+ ThrowUserError('push_error', { error_message => clean_error($@) });
+ }
+ }
+
+ # update
+ foreach my $option ($config->options) {
+ my $option_name = $option->{name};
+ trick_taint($values->{$option_name});
+ $config->{$option_name} = $values->{$option_name};
+ }
+ $config->update();
+}
+
+sub admin_queues {
+ my ($vars, $page) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
+
+ if ($page eq 'push_queues.html') {
+ $vars->{push} = $push;
+
+ } elsif ($page eq 'push_queues_view.html') {
+ my $queue;
+ if ($input->{connector}) {
+ my $connector = $push->connectors->by_name($input->{connector})
+ || ThrowUserError('push_error', { error_message => 'Invalid connector' });
+ $queue = $connector->backlog;
+ } else {
+ $queue = $push->queue;
+ }
+ $vars->{queue} = $queue;
+
+ my $id = $input->{message} || 0;
+ detaint_natural($id)
+ || ThrowUserError('push_error', { error_message => 'Invalid message ID' });
+ my $message = $queue->by_id($id)
+ || ThrowUserError('push_error', { error_message => 'Invalid message ID' });
+
+ if ($input->{delete}) {
+ $message->remove_from_db();
+ $vars->{message} = 'push_message_deleted';
+
+ } else {
+ $vars->{message_obj} = $message;
+ eval {
+ $vars->{json} = to_json($message->payload_decoded, 1);
+ };
+ }
+ }
+}
+
+sub admin_log {
+ my ($vars) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
+
+ $vars->{push} = $push;
+}
+
+1;
diff --git a/extensions/Push/lib/BacklogMessage.pm b/extensions/Push/lib/BacklogMessage.pm
new file mode 100644
index 000000000..8f5263038
--- /dev/null
+++ b/extensions/Push/lib/BacklogMessage.pm
@@ -0,0 +1,149 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::BacklogMessage;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Object';
+
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+
+use Bugzilla;
+use Bugzilla::Error;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Util;
+use Encode;
+
+#
+# initialisation
+#
+
+use constant DB_TABLE => 'push_backlog';
+use constant DB_COLUMNS => qw(
+ id
+ message_id
+ push_ts
+ payload
+ change_set
+ routing_key
+ connector
+ attempt_ts
+ attempts
+ last_error
+);
+use constant UPDATE_COLUMNS => qw(
+ attempt_ts
+ attempts
+ last_error
+);
+use constant LIST_ORDER => 'push_ts';
+use constant VALIDATORS => {
+ payload => \&_check_payload,
+ change_set => \&_check_change_set,
+ routing_key => \&_check_routing_key,
+ connector => \&_check_connector,
+ attempts => \&_check_attempts,
+};
+
+#
+# constructors
+#
+
+sub create_from_message {
+ my ($class, $message, $connector) = @_;
+ my $self = $class->create({
+ message_id => $message->id,
+ push_ts => $message->push_ts,
+ payload => $message->payload,
+ change_set => $message->change_set,
+ routing_key => $message->routing_key,
+ connector => $connector->name,
+ attempt_ts => undef,
+ attempts => 0,
+ last_error => undef,
+ });
+ return $self;
+}
+
+#
+# accessors
+#
+
+sub message_id { return $_[0]->{'message_id'} }
+sub push_ts { return $_[0]->{'push_ts'}; }
+sub payload { return $_[0]->{'payload'}; }
+sub change_set { return $_[0]->{'change_set'}; }
+sub routing_key { return $_[0]->{'routing_key'}; }
+sub connector { return $_[0]->{'connector'}; }
+sub attempt_ts { return $_[0]->{'attempt_ts'}; }
+sub attempts { return $_[0]->{'attempts'}; }
+sub last_error { return $_[0]->{'last_error'}; }
+
+sub payload_decoded {
+ my ($self) = @_;
+ return from_json($self->{'payload'});
+}
+
+sub attempt_time {
+ my ($self) = @_;
+ if (!exists $self->{'attempt_time'}) {
+ $self->{'attempt_time'} = datetime_from($self->attempt_ts)->epoch;
+ }
+ return $self->{'attempt_time'};
+}
+
+#
+# mutators
+#
+
+sub inc_attempts {
+ my ($self, $error) = @_;
+ $self->{attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ $self->{attempts} = $self->{attempts} + 1;
+ $self->{last_error} = $error;
+ $self->update;
+}
+
+#
+# validators
+#
+
+sub _check_payload {
+ my ($invocant, $value) = @_;
+ length($value) || ThrowCodeError('push_invalid_payload');
+ return $value;
+}
+
+sub _check_change_set {
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value)) || ThrowCodeError('push_invalid_change_set');
+ return $value;
+}
+
+sub _check_routing_key {
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value)) || ThrowCodeError('push_invalid_routing_key');
+ return $value;
+}
+
+sub _check_connector {
+ my ($invocant, $value) = @_;
+ Bugzilla->push_ext->connectors->exists($value) || ThrowCodeError('push_invalid_connector');
+ return $value;
+}
+
+sub _check_attempts {
+ my ($invocant, $value) = @_;
+ return $value || 0;
+}
+
+1;
+
diff --git a/extensions/Push/lib/BacklogQueue.pm b/extensions/Push/lib/BacklogQueue.pm
new file mode 100644
index 000000000..79b9b72ee
--- /dev/null
+++ b/extensions/Push/lib/BacklogQueue.pm
@@ -0,0 +1,127 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::BacklogQueue;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Extension::Push::BacklogMessage;
+
+sub new {
+ my ($class, $connector) = @_;
+ my $self = {};
+ bless($self, $class);
+ $self->{connector} = $connector;
+ return $self;
+}
+
+sub count {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("
+ SELECT COUNT(*)
+ FROM push_backlog
+ WHERE connector = ?",
+ undef,
+ $self->{connector});
+}
+
+sub oldest {
+ my ($self) = @_;
+ my @messages = $self->list(
+ limit => 1,
+ filter => 'AND ((next_attempt_ts IS NULL) OR (next_attempt_ts <= NOW()))',
+ );
+ return scalar(@messages) ? $messages[0] : undef;
+}
+
+sub by_id {
+ my ($self, $id) = @_;
+ my @messages = $self->list(
+ limit => 1,
+ filter => "AND (log.id = $id)",
+ );
+ return scalar(@messages) ? $messages[0] : undef;
+}
+
+sub list {
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
+
+ my $filter_sql = $args{filter} || '';
+ my $sth = $dbh->prepare("
+ SELECT log.id, message_id, push_ts, payload, change_set, routing_key, attempt_ts, log.attempts
+ FROM push_backlog log
+ LEFT JOIN push_backoff off ON off.connector = log.connector
+ WHERE log.connector = ? ".
+ $args{filter} . "
+ ORDER BY push_ts " .
+ $dbh->sql_limit($args{limit})
+ );
+ $sth->execute($self->{connector});
+ while (my $row = $sth->fetchrow_hashref()) {
+ push @result, Bugzilla::Extension::Push::BacklogMessage->new({
+ id => $row->{id},
+ message_id => $row->{message_id},
+ push_ts => $row->{push_ts},
+ payload => $row->{payload},
+ change_set => $row->{change_set},
+ routing_key => $row->{routing_key},
+ connector => $self->{connector},
+ attempt_ts => $row->{attempt_ts},
+ attempts => $row->{attempts},
+ });
+ }
+ return @result;
+}
+
+#
+# backoff
+#
+
+sub backoff {
+ my ($self) = @_;
+ if (!$self->{backoff}) {
+ my $ra = Bugzilla::Extension::Push::Backoff->match({
+ connector => $self->{connector}
+ });
+ if (@$ra) {
+ $self->{backoff} = $ra->[0];
+ } else {
+ $self->{backoff} = Bugzilla::Extension::Push::Backoff->create({
+ connector => $self->{connector}
+ });
+ }
+ }
+ return $self->{backoff};
+}
+
+sub reset_backoff {
+ my ($self) = @_;
+ my $backoff = $self->backoff;
+ $backoff->reset();
+ $backoff->update();
+}
+
+sub inc_backoff {
+ my ($self) = @_;
+ my $backoff = $self->backoff;
+ $backoff->inc();
+ $backoff->update();
+}
+
+sub connector {
+ my ($self) = @_;
+ return $self->{connector};
+}
+
+1;
diff --git a/extensions/Push/lib/Backoff.pm b/extensions/Push/lib/Backoff.pm
new file mode 100644
index 000000000..05ee0a775
--- /dev/null
+++ b/extensions/Push/lib/Backoff.pm
@@ -0,0 +1,109 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Backoff;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Object';
+
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+
+use Bugzilla;
+use Bugzilla::Util;
+
+#
+# initialisation
+#
+
+use constant DB_TABLE => 'push_backoff';
+use constant DB_COLUMNS => qw(
+ id
+ connector
+ next_attempt_ts
+ attempts
+);
+use constant UPDATE_COLUMNS => qw(
+ next_attempt_ts
+ attempts
+);
+use constant VALIDATORS => {
+ connector => \&_check_connector,
+ next_attempt_ts => \&_check_next_attempt_ts,
+ attempts => \&_check_attempts,
+};
+use constant LIST_ORDER => 'next_attempt_ts';
+
+#
+# accessors
+#
+
+sub connector { return $_[0]->{'connector'}; }
+sub next_attempt_ts { return $_[0]->{'next_attempt_ts'}; }
+sub attempts { return $_[0]->{'attempts'}; }
+
+sub next_attempt_time {
+ my ($self) = @_;
+ if (!exists $self->{'next_attempt_time'}) {
+ $self->{'next_attempt_time'} = datetime_from($self->next_attempt_ts)->epoch;
+ }
+ return $self->{'next_attempt_time'};
+}
+
+#
+# mutators
+#
+
+sub reset {
+ my ($self) = @_;
+ $self->{next_attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ $self->{attempts} = 0;
+ Bugzilla->push_ext->logger->debug(
+ sprintf("resetting backoff for %s", $self->connector)
+ );
+}
+
+sub inc {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $attempts = $self->attempts + 1;
+ my $seconds = $attempts <= 4 ? 5 ** $attempts : 15 * 60;
+ my ($date) = $dbh->selectrow_array("SELECT " . $dbh->sql_date_math('NOW()', '+', $seconds, 'SECOND'));
+
+ $self->{next_attempt_ts} = $date;
+ $self->{attempts} = $attempts;
+ Bugzilla->push_ext->logger->debug(
+ sprintf("setting next attempt for %s to %s (attempt %s)", $self->connector, $date, $attempts)
+ );
+}
+
+#
+# validators
+#
+
+sub _check_connector {
+ my ($invocant, $value) = @_;
+ Bugzilla->push_ext->connectors->exists($value) || ThrowCodeError('push_invalid_connector');
+ return $value;
+}
+
+sub _check_next_attempt_ts {
+ my ($invocant, $value) = @_;
+ return $value || Bugzilla->dbh->selectrow_array('SELECT NOW()');
+}
+
+sub _check_attempts {
+ my ($invocant, $value) = @_;
+ return $value || 0;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Config.pm b/extensions/Push/lib/Config.pm
new file mode 100644
index 000000000..7033b4195
--- /dev/null
+++ b/extensions/Push/lib/Config.pm
@@ -0,0 +1,215 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Config;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Option;
+use Crypt::CBC;
+
+sub new {
+ my ($class, $name, @options) = @_;
+ my $self = {
+ _name => $name
+ };
+ bless($self, $class);
+
+ $self->{_options} = [@options];
+ unshift @{$self->{_options}}, {
+ name => 'enabled',
+ label => 'Status',
+ help => '',
+ type => 'select',
+ values => [ 'Enabled', 'Disabled' ],
+ default => 'Disabled',
+ };
+
+ return $self;
+}
+
+sub options {
+ my ($self) = @_;
+ return @{$self->{_options}};
+}
+
+sub option {
+ my ($self, $name) = @_;
+ foreach my $option ($self->options) {
+ return $option if $option->{name} eq $name;
+ }
+ return undef;
+}
+
+sub load {
+ my ($self) = @_;
+ my $config = {};
+ my $logger = Bugzilla->push_ext->logger;
+
+ # prime $config with defaults
+ foreach my $rh ($self->options) {
+ $config->{$rh->{name}} = $rh->{default};
+ }
+
+ # override defaults with values from database
+ my $options = Bugzilla::Extension::Push::Option->match({
+ connector => $self->{_name},
+ });
+ foreach my $option (@$options) {
+ my $option_config = $self->option($option->name)
+ || next;
+ if ($option_config->{type} eq 'password') {
+ $config->{$option->name} = $self->_decrypt($option->value);
+ } else {
+ $config->{$option->name} = $option->value;
+ }
+ }
+
+ # validate when running from the daemon
+ if (Bugzilla->push_ext->is_daemon) {
+ $self->_validate_config($config);
+ }
+
+ # done, update self
+ foreach my $name (keys %$config) {
+ my $value = $self->option($name)->{type} eq 'password' ? '********' : $config->{$name};
+ $logger->debug(sprintf("%s: set %s=%s\n", $self->{_name}, $name, $value || ''));
+ $self->{$name} = $config->{$name};
+ }
+}
+
+sub validate {
+ my ($self, $config) = @_;
+ $self->_validate_mandatory($config);
+ $self->_validate_config($config);
+}
+
+sub update {
+ my ($self) = @_;
+
+ my @valid_options = map { $_->{name} } $self->options;
+
+ my %options;
+ my $options_list = Bugzilla::Extension::Push::Option->match({
+ connector => $self->{_name},
+ });
+ foreach my $option (@$options_list) {
+ $options{$option->name} = $option;
+ }
+
+ # delete options which are no longer valid
+ foreach my $name (keys %options) {
+ if (!grep { $_ eq $name } @valid_options) {
+ $options{$name}->remove_from_db();
+ delete $options{$name};
+ }
+ }
+
+ # update options
+ foreach my $name (keys %options) {
+ my $option = $options{$name};
+ if ($self->option($name)->{type} eq 'password') {
+ $option->set_value($self->_encrypt($self->{$name}));
+ } else {
+ $option->set_value($self->{$name});
+ }
+ $option->update();
+ }
+
+ # add missing options
+ foreach my $name (@valid_options) {
+ next if exists $options{$name};
+ Bugzilla::Extension::Push::Option->create({
+ connector => $self->{_name},
+ option_name => $name,
+ option_value => $self->{$name},
+ });
+ }
+}
+
+sub _remove_invalid_options {
+ my ($self, $config) = @_;
+ my @names;
+ foreach my $rh ($self->options) {
+ push @names, $rh->{name};
+ }
+ foreach my $name (keys %$config) {
+ if ($name =~ /^_/ || !grep { $_ eq $name } @names) {
+ delete $config->{$name};
+ }
+ }
+}
+
+sub _validate_mandatory {
+ my ($self, $config) = @_;
+ $self->_remove_invalid_options($config);
+
+ my @missing;
+ foreach my $option ($self->options) {
+ next unless $option->{required};
+ my $name = $option->{name};
+ if (!exists $config->{$name} || !defined($config->{$name}) || $config->{$name} eq '') {
+ push @missing, $option;
+ }
+ }
+ if (@missing) {
+ my $connector = $self->{_name};
+ @missing = map { $_->{label} } @missing;
+ if (scalar @missing == 1) {
+ die "The option '$missing[0]' for the connector '$connector' is mandatory\n";
+ } else {
+ die "The following options for the connector '$connector' are mandatory:\n "
+ . join("\n ", @missing) . "\n";
+ }
+ }
+}
+
+sub _validate_config {
+ my ($self, $config) = @_;
+ $self->_remove_invalid_options($config);
+
+ my @errors;
+ foreach my $option ($self->options) {
+ my $name = $option->{name};
+ next unless exists $config->{$name} && exists $option->{validate};
+ eval {
+ $option->{validate}->($config->{$name}, $config);
+ };
+ push @errors, $@ if $@;
+ }
+ die join("\n", @errors) if @errors;
+
+ if ($self->{_name} ne 'global') {
+ my $class = 'Bugzilla::Extension::Push::Connector::' . $self->{_name};
+ $class->options_validate($config);
+ }
+}
+
+sub _cipher {
+ my ($self) = @_;
+ $self->{_cipher} ||= Crypt::CBC->new(
+ -key => Bugzilla->localconfig->{'site_wide_secret'},
+ -cipher => 'DES_EDE3');
+ return $self->{_cipher};
+}
+
+sub _decrypt {
+ my ($self, $value) = @_;
+ my $result;
+ eval { $result = $self->_cipher->decrypt_hex($value) };
+ return $@ ? '' : $result;
+}
+
+sub _encrypt {
+ my ($self, $value) = @_;
+ return $self->_cipher->encrypt_hex($value);
+}
+
+1;
diff --git a/extensions/Push/lib/Connector.disabled/ServiceNow.pm b/extensions/Push/lib/Connector.disabled/ServiceNow.pm
new file mode 100644
index 000000000..832cc9262
--- /dev/null
+++ b/extensions/Push/lib/Connector.disabled/ServiceNow.pm
@@ -0,0 +1,434 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connector::ServiceNow;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Extension::Push::Connector::Base';
+
+use Bugzilla::Attachment;
+use Bugzilla::Bug;
+use Bugzilla::Component;
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::Serialise;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Field;
+use Bugzilla::Mailer;
+use Bugzilla::Product;
+use Bugzilla::User;
+use Bugzilla::Util qw(trim trick_taint);
+use Email::MIME;
+use FileHandle;
+use LWP;
+use MIME::Base64;
+use Net::LDAP;
+
+use constant SEND_COMPONENTS => (
+ {
+ product => 'mozilla.org',
+ component => 'Server Operations: Desktop Issues',
+ },
+);
+
+sub options {
+ return (
+ {
+ name => 'bugzilla_user',
+ label => 'Bugzilla Service-Now User',
+ type => 'string',
+ default => 'service.now@bugzilla.tld',
+ required => 1,
+ validate => sub {
+ Bugzilla::User->new({ name => $_[0] })
+ || die "Invalid Bugzilla user ($_[0])\n";
+ },
+ },
+ {
+ name => 'ldap_scheme',
+ label => 'Mozilla LDAP Scheme',
+ type => 'select',
+ values => [ 'LDAP', 'LDAPS' ],
+ default => 'LDAPS',
+ required => 1,
+ },
+ {
+ name => 'ldap_host',
+ label => 'Mozilla LDAP Host',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_user',
+ label => 'Mozilla LDAP Bind Username',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_pass',
+ label => 'Mozilla LDAP Password',
+ type => 'password',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_poll',
+ label => 'Mozilla LDAP Poll Frequency',
+ type => 'string',
+ default => '3',
+ required => 1,
+ help => 'minutes',
+ validate => sub {
+ $_[0] =~ /\D/
+ && die "LDAP Poll Frequency must be an integer\n";
+ $_[0] == 0
+ && die "LDAP Poll Frequency cannot be less than one minute\n";
+ },
+ },
+ {
+ name => 'service_now_url',
+ label => 'Service Now JSON URL',
+ type => 'string',
+ default => 'https://mozilladev.service-now.com',
+ required => 1,
+ help => "Must start with https:// and end with ?JSON",
+ validate => sub {
+ $_[0] =~ m#^https://[^\.\/]+\.service-now\.com\/#
+ || die "Invalid Service Now JSON URL\n";
+ $_[0] =~ m#\?JSON$#
+ || die "Invalid Service Now JSON URL (must end with ?JSON)\n";
+ },
+ },
+ {
+ name => 'service_now_user',
+ label => 'Service Now JSON Username',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'service_now_pass',
+ label => 'Service Now JSON Password',
+ type => 'password',
+ default => '',
+ required => 1,
+ },
+ );
+}
+
+sub options_validate {
+ my ($self, $config) = @_;
+ my $host = $config->{ldap_host};
+ trick_taint($host);
+ my $scheme = lc($config->{ldap_scheme});
+ eval {
+ my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die', timeout => 5)
+ or die $!;
+ $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
+ };
+ if ($@) {
+ die sprintf("Failed to connect to %s://%s/: %s\n", $scheme, $host, $@);
+ }
+}
+
+my $_instance;
+
+sub init {
+ my ($self) = @_;
+ $_instance = $self;
+}
+
+sub load_config {
+ my ($self) = @_;
+ $self->SUPER::load_config(@_);
+ $self->{bugzilla_user} ||= Bugzilla::User->new({ name => $self->config->{bugzilla_user} });
+}
+
+sub should_send {
+ my ($self, $message) = @_;
+
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data)
+ || return 0;
+
+ # we don't want to send the initial comment in a separate message
+ # because we inject it into the inital message
+ if (exists $data->{comment} && $data->{comment}->{number} == 0) {
+ return 0;
+ }
+
+ my $target = $data->{event}->{target};
+ unless ($target eq 'bug' || $target eq 'comment' || $target eq 'attachment') {
+ return 0;
+ }
+
+ # ensure the service-now user can see the bug
+ if (!$self->{bugzilla_user} || !$self->{bugzilla_user}->is_enabled) {
+ return 0;
+ }
+ $self->{bugzilla_user}->can_see_bug($bug_data->{id})
+ || return 0;
+
+ # don't push changes made by the service-now account
+ $data->{event}->{user}->{id} == $self->{bugzilla_user}->id
+ && return 0;
+
+ # filter based on the component
+ my $bug = Bugzilla::Bug->new($bug_data->{id});
+ my $send = 0;
+ foreach my $rh (SEND_COMPONENTS) {
+ if ($bug->product eq $rh->{product} && $bug->component eq $rh->{component}) {
+ $send = 1;
+ last;
+ }
+ }
+ return $send;
+}
+
+sub send {
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # should_send intiailises bugzilla_user; make sure we return a useful error message
+ if (!$self->{bugzilla_user}) {
+ return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{bugzilla_user} . ")");
+ }
+
+ # load the bug
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data);
+ my $bug = Bugzilla::Bug->new($bug_data->{id});
+
+ if ($message->routing_key eq 'bug.create') {
+ # inject the comment into the data for new bugs
+ my $comment = shift @{ $bug->comments };
+ if ($comment->body ne '') {
+ $bug_data->{comment} = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($comment, 1);
+ }
+
+ } elsif ($message->routing_key eq 'attachment.create') {
+ # inject the attachment payload
+ my $attachment = Bugzilla::Attachment->new($data->{attachment}->{id});
+ $data->{attachment}->{data} = encode_base64($attachment->data);
+ }
+
+ # map bmo login to ldap login and insert into json payload
+ $self->_add_ldap_logins($data, {});
+
+ # flatten json data
+ $self->_flatten($data);
+
+ # add sysparm_action
+ $data->{sysparm_action} = 'insert';
+
+ if ($logger->debugging) {
+ $logger->debug(to_json(ref($data) ? $data : from_json($data), 1));
+ }
+
+ # send to service-now
+ my $request = HTTP::Request->new(POST => $self->config->{service_now_url});
+ $request->content_type('application/json');
+ $request->content(to_json($data));
+ $request->authorization_basic($self->config->{service_now_user}, $self->config->{service_now_pass});
+
+ $self->{lwp} ||= LWP::UserAgent->new(agent => Bugzilla->params->{urlbase});
+ my $result = $self->{lwp}->request($request);
+
+ # http level errors
+ if (!$result->is_success) {
+ # treat these as transient
+ return (PUSH_RESULT_TRANSIENT, $result->status_line);
+ }
+
+ # empty response
+ if (length($result->content) == 0) {
+ # malformed request, treat as transient to allow code to fix
+ # may also be misconfiguration on servicenow, also transient
+ return (PUSH_RESULT_TRANSIENT, "Empty response");
+ }
+
+ # json errors
+ my $result_data;
+ eval {
+ $result_data = from_json($result->content);
+ };
+ if ($@) {
+ return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ }
+ if ($logger->debugging) {
+ $logger->debug(to_json($result_data, 1));
+ }
+ if (exists $result_data->{error}) {
+ return (PUSH_RESULT_ERROR, $result_data->{error});
+ };
+
+ # malformed/unexpected json response
+ if (!exists $result_data->{records}
+ || ref($result_data->{records}) ne 'ARRAY'
+ || scalar(@{$result_data->{records}}) == 0
+ ) {
+ return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: missing or empty 'records' array");
+ }
+
+ my $record = $result_data->{records}->[0];
+ if (ref($record) ne 'HASH') {
+ return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records' array does not contain an object");
+ }
+
+ # sys_id is the unique identifier for this action
+ if (!exists $record->{sys_id} || $record->{sys_id} eq '') {
+ return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records object' does not contain a valid sys_id");
+ }
+
+ # success
+ return (PUSH_RESULT_OK, "sys_id: " . $record->{sys_id});
+}
+
+sub _get_bug_data {
+ my ($self, $data) = @_;
+ my $target = $data->{event}->{target};
+ if ($target eq 'bug') {
+ return $data->{bug};
+ } elsif (exists $data->{$target}->{bug}) {
+ return $data->{$target}->{bug};
+ } else {
+ return;
+ }
+}
+
+sub _flatten {
+ # service-now expects a flat json object
+ my ($self, $data) = @_;
+
+ my $target = $data->{event}->{target};
+
+ # delete unnecessary deep objects
+ if ($target eq 'comment' || $target eq 'attachment') {
+ $data->{$target}->{bug_id} = $data->{$target}->{bug}->{id};
+ delete $data->{$target}->{bug};
+ }
+ delete $data->{event}->{changes};
+
+ $self->_flatten_hash($data, $data, 'u');
+}
+
+sub _flatten_hash {
+ my ($self, $base_hash, $hash, $prefix) = @_;
+ foreach my $key (keys %$hash) {
+ if (ref($hash->{$key}) eq 'HASH') {
+ $self->_flatten_hash($base_hash, $hash->{$key}, $prefix . "_$key");
+ } elsif (ref($hash->{$key}) ne 'ARRAY') {
+ $base_hash->{$prefix . "_$key"} = $hash->{$key};
+ }
+ delete $hash->{$key};
+ }
+}
+
+sub _add_ldap_logins {
+ my ($self, $rh, $cache) = @_;
+ if (exists $rh->{login}) {
+ my $login = $rh->{login};
+ $cache->{$login} ||= $self->_bmo_to_ldap($login);
+ Bugzilla->push_ext->logger->debug("BMO($login) --> LDAP(" . $cache->{$login} . ")");
+ $rh->{ldap} = $cache->{$login};
+ }
+ foreach my $key (keys %$rh) {
+ next unless ref($rh->{$key}) eq 'HASH';
+ $self->_add_ldap_logins($rh->{$key}, $cache);
+ }
+}
+
+sub _bmo_to_ldap {
+ my ($self, $login) = @_;
+ my $ldap = $self->_ldap_cache();
+
+ return '' unless $login =~ /\@mozilla\.(?:com|org)$/;
+
+ foreach my $check ($login, canon_email($login)) {
+ # check for matching bugmail entry
+ foreach my $mail (keys %$ldap) {
+ next unless $ldap->{$mail}{bugmail_canon} eq $check;
+ return $mail;
+ }
+
+ # check for matching mail
+ if (exists $ldap->{$check}) {
+ return $check;
+ }
+
+ # check for matching email alias
+ foreach my $mail (sort keys %$ldap) {
+ next unless grep { $check eq $_ } @{$ldap->{$mail}{aliases}};
+ return $mail;
+ }
+ }
+
+ return '';
+}
+
+sub _ldap_cache {
+ my ($self) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # cache of all ldap entries; updated infrequently
+ if (!$self->{ldap_cache_time} || (time) - $self->{ldap_cache_time} > $config->{ldap_poll} * 60) {
+ $logger->debug('refreshing LDAP cache');
+
+ my $cache = {};
+
+ my $host = $config->{ldap_host};
+ trick_taint($host);
+ my $scheme = lc($config->{ldap_scheme});
+ my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die')
+ or die $!;
+ $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
+ foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') {
+ my $result = $ldap->search(
+ base => $ldap_base,
+ scope => 'sub',
+ filter => '(mail=*)',
+ attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'],
+ );
+ foreach my $entry ($result->entries) {
+ my ($name, $bugMail, $mail, $type) =
+ map { $entry->get_value($_) || '' }
+ qw(cn bugzillaEmail mail employeeType);
+ next if $type eq 'DISABLED';
+ $mail = lc $mail;
+ $bugMail = '' if $bugMail !~ /\@/;
+ $bugMail = trim($bugMail);
+ if ($bugMail =~ / /) {
+ $bugMail = (grep { /\@/ } split / /, $bugMail)[0];
+ }
+ $name =~ s/\s+/ /g;
+ $cache->{$mail}{name} = trim($name);
+ $cache->{$mail}{bugmail} = $bugMail;
+ $cache->{$mail}{bugmail_canon} = canon_email($bugMail);
+ $cache->{$mail}{aliases} = [];
+ foreach my $alias (
+ @{$entry->get_value('emailAlias', asref => 1) || []}
+ ) {
+ push @{$cache->{$mail}{aliases}}, canon_email($alias);
+ }
+ }
+ }
+
+ $self->{ldap_cache} = $cache;
+ $self->{ldap_cache_time} = (time);
+ }
+
+ return $self->{ldap_cache};
+}
+
+1;
+
diff --git a/extensions/Push/lib/Connector/AMQP.pm b/extensions/Push/lib/Connector/AMQP.pm
new file mode 100644
index 000000000..7b7d4aa72
--- /dev/null
+++ b/extensions/Push/lib/Connector/AMQP.pm
@@ -0,0 +1,230 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connector::AMQP;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Extension::Push::Connector::Base';
+
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Util qw(generate_random_password);
+use DateTime;
+
+sub init {
+ my ($self) = @_;
+ $self->{mq} = 0;
+ $self->{channel} = 1;
+
+ if ($self->config->{queue}) {
+ $self->{queue_name} = $self->config->{queue};
+ } else {
+ my $queue_name = Bugzilla->params->{'urlbase'};
+ $queue_name =~ s#^https?://##;
+ $queue_name =~ s#/$#|#;
+ $queue_name .= generate_random_password(16);
+ $self->{queue_name} = $queue_name;
+ }
+}
+
+sub options {
+ return (
+ {
+ name => 'host',
+ label => 'AMQP Hostname',
+ type => 'string',
+ default => 'localhost',
+ required => 1,
+ },
+ {
+ name => 'port',
+ label => 'AMQP Port',
+ type => 'string',
+ default => '5672',
+ required => 1,
+ validate => sub {
+ $_[0] =~ /\D/ && die "Invalid port (must be numeric)\n";
+ },
+ },
+ {
+ name => 'username',
+ label => 'Username',
+ type => 'string',
+ default => 'guest',
+ required => 1,
+ },
+ {
+ name => 'password',
+ label => 'Password',
+ type => 'password',
+ default => 'guest',
+ required => 1,
+ },
+ {
+ name => 'vhost',
+ label => 'Virtual Host',
+ type => 'string',
+ default => '/',
+ required => 1,
+ },
+ {
+ name => 'exchange',
+ label => 'Exchange',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'queue',
+ label => 'Queue',
+ type => 'string',
+ },
+ );
+}
+
+sub stop {
+ my ($self) = @_;
+ if ($self->{mq}) {
+ Bugzilla->push_ext->logger->debug('AMQP: disconnecting');
+ $self->{mq}->disconnect();
+ $self->{mq} = 0;
+ }
+}
+
+sub _connect {
+ my ($self) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ $self->stop();
+
+ $logger->debug('AMQP: Connecting to RabbitMQ ' . $config->{host} . ':' . $config->{port});
+ require Net::RabbitMQ;
+ my $mq = Net::RabbitMQ->new();
+ $mq->connect(
+ $config->{host},
+ {
+ port => $config->{port},
+ user => $config->{username},
+ password => $config->{password},
+ }
+ );
+ $self->{mq} = $mq;
+
+ $logger->debug('AMQP: Opening channel ' . $self->{channel});
+ $self->{mq}->channel_open($self->{channel});
+
+ $logger->debug('AMQP: Declaring queue ' . $self->{queue_name});
+ $self->{mq}->queue_declare(
+ $self->{channel},
+ $self->{queue_name},
+ {
+ passive => 0,
+ durable => 1,
+ exclusive => 0,
+ auto_delete => 0,
+ },
+ );
+}
+
+sub _bind {
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # bind to queue (also acts to verify the connection is still valid)
+ if ($self->{mq}) {
+ eval {
+ $logger->debug('AMQP: binding queue(' . $self->{queue_name} . ') with exchange(' . $config->{exchange} . ')');
+ $self->{mq}->queue_bind(
+ $self->{channel},
+ $self->{queue_name},
+ $config->{exchange},
+ $message->routing_key,
+ );
+ };
+ if ($@) {
+ $logger->debug('AMQP: ' . clean_error($@));
+ $self->{mq} = 0;
+ }
+ }
+
+}
+
+sub should_send {
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+
+ my $payload = $message->payload_decoded();
+ my $target = $payload->{event}->{target};
+ my $is_private = $payload->{$target}->{is_private} ? 1 : 0;
+ if (!$is_private && exists $payload->{$target}->{bug}) {
+ $is_private = $payload->{$target}->{bug}->{is_private} ? 1 : 0;
+ }
+
+ if ($is_private) {
+ # we only want to push the is_private message from the change_set, as
+ # this is guaranteed to contain public information only
+ if ($message->routing_key !~ /\.modify:is_private$/) {
+ $logger->debug('AMQP: Ignoring private message');
+ return 0;
+ }
+ $logger->debug('AMQP: Sending change of message to is_private');
+ }
+ return 1;
+}
+
+sub send {
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # don't push comments to pulse
+ if ($message->routing_key =~ /^comment\./) {
+ $logger->debug('AMQP: Ignoring comment');
+ return PUSH_RESULT_IGNORED;
+ }
+
+ # don't push private data
+ $self->should_push($message)
+ || return PUSH_RESULT_IGNORED;
+
+ $self->_bind($message);
+
+ eval {
+ # reconnect if required
+ if (!$self->{mq}) {
+ $self->_connect();
+ }
+
+ # send message
+ $logger->debug('AMQP: Publishing message');
+ $self->{mq}->publish(
+ $self->{channel},
+ $message->routing_key,
+ $message->payload,
+ {
+ exchange => $config->{exchange},
+ },
+ {
+ content_type => 'text/plain',
+ content_encoding => '8bit',
+ },
+ );
+ };
+ if ($@) {
+ return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ }
+
+ return PUSH_RESULT_OK;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Connector/Base.pm b/extensions/Push/lib/Connector/Base.pm
new file mode 100644
index 000000000..290ea9740
--- /dev/null
+++ b/extensions/Push/lib/Connector/Base.pm
@@ -0,0 +1,106 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connector::Base;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Extension::Push::Config;
+use Bugzilla::Extension::Push::BacklogMessage;
+use Bugzilla::Extension::Push::BacklogQueue;
+use Bugzilla::Extension::Push::Backoff;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ ($self->{name}) = $class =~ /^.+:(.+)$/;
+ $self->init();
+ return $self;
+}
+
+sub name {
+ my $self = shift;
+ return $self->{name};
+}
+
+sub init {
+ my ($self) = @_;
+ # abstract
+ # perform any initialisation here
+ # will be run when created by the web pages or by the daemon
+ # and also when the configuration needs to be reloaded
+}
+
+sub stop {
+ my ($self) = @_;
+ # abstract
+ # run from the daemon only; disconnect from remote hosts, etc
+}
+
+sub should_send {
+ my ($self, $message) = @_;
+ # abstract
+ # return boolean indicating if the connector will be sending the message.
+ # this will be called each message, and should be a very quick simple test.
+ # the connector can perform a more exhaustive test in the send() method.
+ return 0;
+}
+
+sub send {
+ my ($self, $message) = @_;
+ # abstract
+ # deliver the message, daemon only
+}
+
+sub options {
+ my ($self) = @_;
+ # abstract
+ # return an array of configuration variables
+ return ();
+}
+
+sub options_validate {
+ my ($class, $config) = @_;
+ # abstract, static
+ # die if a combination of options in $config is invalid
+}
+
+#
+#
+#
+
+sub config {
+ my ($self) = @_;
+ if (!$self->{config}) {
+ $self->load_config();
+ }
+ return $self->{config};
+}
+
+sub load_config {
+ my ($self) = @_;
+ my $config = Bugzilla::Extension::Push::Config->new($self->name, $self->options);
+ $config->load();
+ $self->{config} = $config;
+}
+
+sub enabled {
+ my ($self) = @_;
+ return $self->config->{enabled} eq 'Enabled';
+}
+
+sub backlog {
+ my ($self) = @_;
+ $self->{backlog} ||= Bugzilla::Extension::Push::BacklogQueue->new($self->name);
+ return $self->{backlog};
+}
+
+1;
+
diff --git a/extensions/Push/lib/Connector/File.pm b/extensions/Push/lib/Connector/File.pm
new file mode 100644
index 000000000..2a8f4193d
--- /dev/null
+++ b/extensions/Push/lib/Connector/File.pm
@@ -0,0 +1,68 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connector::File;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Extension::Push::Connector::Base';
+
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::Util;
+use Encode;
+use FileHandle;
+
+sub init {
+ my ($self) = @_;
+}
+
+sub options {
+ return (
+ {
+ name => 'filename',
+ label => 'Filename',
+ type => 'string',
+ default => 'push.log',
+ required => 1,
+ validate => sub {
+ my $filename = shift;
+ $filename =~ m#^/#
+ && die "Absolute paths are not permitted\n";
+ },
+ },
+ );
+}
+
+sub should_send {
+ my ($self, $message) = @_;
+ return 1;
+}
+
+sub send {
+ my ($self, $message) = @_;
+
+ # pretty-format json payload
+ my $payload = $message->payload_decoded;
+ $payload = to_json($payload, 1);
+
+ my $filename = bz_locations()->{'datadir'} . '/' . $self->config->{filename};
+ Bugzilla->push_ext->logger->debug("File: Appending to $filename");
+ my $fh = FileHandle->new(">>$filename");
+ $fh->binmode(':utf8');
+ $fh->print(
+ "[" . scalar(localtime) . "]\n" .
+ $payload . "\n\n"
+ );
+ $fh->close;
+
+ return PUSH_RESULT_OK;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Connector/TCL.pm b/extensions/Push/lib/Connector/TCL.pm
new file mode 100644
index 000000000..6207e2eac
--- /dev/null
+++ b/extensions/Push/lib/Connector/TCL.pm
@@ -0,0 +1,349 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connector::TCL;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Extension::Push::Connector::Base';
+
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::Serialise;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::User;
+use Bugzilla::Attachment;
+
+use Digest::MD5 qw(md5_hex);
+use Encode qw(encode_utf8);
+
+sub options {
+ return (
+ {
+ name => 'tcl_user',
+ label => 'Bugzilla TCL User',
+ type => 'string',
+ default => 'tcl@bugzilla.tld',
+ required => 1,
+ validate => sub {
+ Bugzilla::User->new({ name => $_[0] })
+ || die "Invalid Bugzilla user ($_[0])\n";
+ },
+ },
+ {
+ name => 'sftp_host',
+ label => 'SFTP Host',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'sftp_port',
+ label => 'SFTP Port',
+ type => 'string',
+ default => '22',
+ required => 1,
+ validate => sub {
+ $_[0] =~ /\D/ && die "SFTP Port must be an integer\n";
+ },
+ },
+ {
+ name => 'sftp_user',
+ label => 'SFTP Username',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'sftp_pass',
+ label => 'SFTP Password',
+ type => 'password',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'sftp_remote_path',
+ label => 'SFTP Remote Path',
+ type => 'string',
+ default => '',
+ required => 0,
+ },
+ );
+}
+
+my $_instance;
+
+sub init {
+ my ($self) = @_;
+ $_instance = $self;
+}
+
+sub load_config {
+ my ($self) = @_;
+ $self->SUPER::load_config(@_);
+}
+
+sub should_send {
+ my ($self, $message) = @_;
+
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data)
+ || return 0;
+
+ # sanity check user
+ $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} });
+ if (!$self->{tcl_user} || !$self->{tcl_user}->is_enabled) {
+ return 0;
+ }
+
+ # only send bugs created by the tcl user
+ unless ($bug_data->{reporter}->{id} == $self->{tcl_user}->id) {
+ return 0;
+ }
+
+ # don't push changes made by the tcl user
+ if ($data->{event}->{user}->{id} == $self->{tcl_user}->id) {
+ return 0;
+ }
+
+ # send comments
+ if ($data->{event}->{routing_key} eq 'comment.create') {
+ return 0 if $data->{comment}->{is_private};
+ return 1;
+ }
+
+ # send status and resolution updates
+ foreach my $change (@{ $data->{event}->{changes} }) {
+ return 1 if $change->{field} eq 'bug_status' || $change->{field} eq 'resolution';
+ }
+
+ # send attachments
+ if ($data->{event}->{routing_key} =~ /^attachment\./) {
+ return 0 if $data->{attachment}->{is_private};
+ return 1;
+ }
+
+ # and nothing else
+ return 0;
+}
+
+sub send {
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ require XML::Simple;
+ require Net::SFTP;
+
+ $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} });
+ if (!$self->{tcl_user}) {
+ return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{tcl_user} . ")");
+ }
+
+ # load the bug
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data);
+
+ # build payload
+ my $attachment;
+ my %xml = (
+ Mozilla_ID => $bug_data->{id},
+ When => $data->{event}->{time},
+ Who => $data->{event}->{user}->{login},
+ Status => $bug_data->{status}->{name},
+ Resolution => $bug_data->{resolution},
+ );
+ if ($data->{event}->{routing_key} eq 'comment.create') {
+ $xml{Comment} = $data->{comment}->{body};
+ } elsif ($data->{event}->{routing_key} =~ /^attachment\.(\w+)/) {
+ my $is_update = $1 eq 'modify';
+ if (!$is_update) {
+ $attachment = Bugzilla::Attachment->new($data->{attachment}->{id});
+ }
+ $xml{Attach} = {
+ Attach_ID => $data->{attachment}->{id},
+ Filename => $data->{attachment}->{file_name},
+ Description => $data->{attachment}->{description},
+ ContentType => $data->{attachment}->{content_type},
+ IsPatch => $data->{attachment}->{is_patch} ? 'true' : 'false',
+ IsObsolete => $data->{attachment}->{is_obsolete} ? 'true' : 'false',
+ IsUpdate => $is_update ? 'true' : 'false',
+ };
+ }
+
+ # convert to xml
+ my $xml = XML::Simple::XMLout(
+ \%xml,
+ NoAttr => 1,
+ RootName => 'sync',
+ XMLDecl => 1,
+ );
+ $xml = encode_utf8($xml);
+
+ # generate md5
+ my $md5 = md5_hex($xml);
+
+ # build filename
+ my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
+ my $change_set = $data->{event}->{change_set};
+ $change_set =~ s/\.//g;
+ my $filename = sprintf(
+ '%04s%02d%02d%02d%02d%02d%s',
+ $year + 1900,
+ $mon + 1,
+ $day,
+ $hour,
+ $min,
+ $sec,
+ $change_set,
+ );
+
+ # create temp files;
+ my $temp_dir = File::Temp::Directory->new();
+ my $local_dir = $temp_dir->dirname;
+ _write_file("$local_dir/$filename.sync", $xml);
+ _write_file("$local_dir/$filename.sync.check", $md5);
+ _write_file("$local_dir/$filename.done", '');
+ if ($attachment) {
+ _write_file("$local_dir/$filename.sync.attach", $attachment->data);
+ }
+
+ my $remote_dir = $self->config->{sftp_remote_path} eq ''
+ ? ''
+ : $self->config->{sftp_remote_path} . '/';
+
+ # send files via sftp
+ $logger->debug("Connecting to " . $self->config->{sftp_host} . ":" . $self->config->{sftp_port});
+ my $sftp = Net::SFTP->new(
+ $self->config->{sftp_host},
+ ssh_args => {
+ port => $self->config->{sftp_port},
+ },
+ user => $self->config->{sftp_user},
+ password => $self->config->{sftp_pass},
+ );
+
+ $logger->debug("Uploading $local_dir/$filename.sync");
+ $sftp->put("$local_dir/$filename.sync", "$remote_dir$filename.sync")
+ or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync");
+
+ $logger->debug("Uploading $local_dir/$filename.sync.check");
+ $sftp->put("$local_dir/$filename.sync.check", "$remote_dir$filename.sync.check")
+ or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.check");
+
+ if ($attachment) {
+ $logger->debug("Uploading $local_dir/$filename.sync.attach");
+ $sftp->put("$local_dir/$filename.sync.attach", "$remote_dir$filename.sync.attach")
+ or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.attach");
+ }
+
+ $logger->debug("Uploading $local_dir/$filename.done");
+ $sftp->put("$local_dir/$filename.done", "$remote_dir$filename.done")
+ or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.done");
+
+ # success
+ return (PUSH_RESULT_OK, "uploaded $filename.sync");
+}
+
+sub _get_bug_data {
+ my ($self, $data) = @_;
+ my $target = $data->{event}->{target};
+ if ($target eq 'bug') {
+ return $data->{bug};
+ } elsif (exists $data->{$target}->{bug}) {
+ return $data->{$target}->{bug};
+ } else {
+ return;
+ }
+}
+
+sub _write_file {
+ my ($filename, $content) = @_;
+ open(my $fh, ">$filename") or die "Failed to write to $filename: $!\n";
+ binmode($fh);
+ print $fh $content;
+ close($fh) or die "Failed to write to $filename: $!\n";
+}
+
+1;
+
+# File::Temp->newdir() requires a newer version of File::Temp than we have on
+# production, so here's a small inline package which performs the same task.
+
+package File::Temp::Directory;
+
+use strict;
+use warnings;
+
+use File::Temp;
+use File::Path qw(rmtree);
+use File::Spec;
+
+my @chars;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+
+ @chars = qw/ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+ a b c d e f g h i j k l m n o p q r s t u v w x y z
+ 0 1 2 3 4 5 6 7 8 9 _
+ /;
+
+ $self->{TEMPLATE} = File::Spec->catdir(File::Spec->tmpdir, 'X' x 10);
+ $self->{DIRNAME} = $self->_mktemp();
+ return $self;
+}
+
+sub _mktemp {
+ my ($self) = @_;
+ my $path = $self->_random_name();
+ while(1) {
+ if (mkdir($path, 0700)) {
+ # in case of odd umask
+ chmod(0700, $path);
+ return $path;
+ } else {
+ # abort with error if the reason for failure was anything except eexist
+ die "Could not create directory $path: $!\n" unless ($!{EEXIST});
+ # loop round for another try
+ }
+ $path = $self->_random_name();
+ }
+
+ return $path;
+}
+
+sub _random_name {
+ my ($self) = @_;
+ my $path = $self->{TEMPLATE};
+ $path =~ s/X/$chars[int(rand(@chars))]/ge;
+ return $path;
+}
+
+sub dirname {
+ my ($self) = @_;
+ return $self->{DIRNAME};
+}
+
+sub DESTROY {
+ my ($self) = @_;
+ local($., $@, $!, $^E, $?);
+ if (-d $self->{DIRNAME}) {
+ # Some versions of rmtree will abort if you attempt to remove the
+ # directory you are sitting in. We protect that and turn it into a
+ # warning. We do this because this occurs during object destruction and
+ # so can not be caught by the user.
+ eval { rmtree($self->{DIRNAME}, 0, 0); };
+ warn $@ if ($@ && $^W);
+ }
+}
+
+1;
+
diff --git a/extensions/Push/lib/Connectors.pm b/extensions/Push/lib/Connectors.pm
new file mode 100644
index 000000000..026d3f7f1
--- /dev/null
+++ b/extensions/Push/lib/Connectors.pm
@@ -0,0 +1,116 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Connectors;
+
+use strict;
+use warnings;
+
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Constants;
+use Bugzilla::Util qw(trick_taint);
+use File::Basename;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+
+ $self->{names} = [];
+ $self->{objects} = {};
+ $self->{path} = bz_locations->{'extensionsdir'} . '/Push/lib/Connector';
+
+ my $logger = Bugzilla->push_ext->logger;
+ foreach my $file (glob($self->{path} . '/*.pm')) {
+ my $name = basename($file);
+ $name =~ s/\.pm$//;
+ next if $name eq 'Base';
+ if (length($name) > 32) {
+ $logger->info("Ignoring connector '$name': Name longer than 32 characters");
+ }
+ push @{$self->{names}}, $name;
+ $logger->debug("Found connector '$name'");
+ }
+
+ return $self;
+}
+
+sub _load {
+ my ($self) = @_;
+ return if scalar keys %{$self->{objects}};
+
+ my $logger = Bugzilla->push_ext->logger;
+ foreach my $name (@{$self->{names}}) {
+ next if exists $self->{objects}->{$name};
+ my $file = $self->{path} . "/$name.pm";
+ trick_taint($file);
+ require $file;
+ my $package = "Bugzilla::Extension::Push::Connector::$name";
+
+ $logger->debug("Loading connector '$name'");
+ my $old_error_mode = Bugzilla->error_mode;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+ eval {
+ my $connector = $package->new();
+ $connector->load_config();
+ $self->{objects}->{$name} = $connector;
+ };
+ if ($@) {
+ $logger->error("Connector '$name' failed to load: " . clean_error($@));
+ }
+ Bugzilla->error_mode($old_error_mode);
+ }
+}
+
+sub stop {
+ my ($self) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ foreach my $connector ($self->list) {
+ next unless $connector->enabled;
+ $logger->debug("Stopping '" . $connector->name . "'");
+ eval {
+ $connector->stop();
+ };
+ if ($@) {
+ $logger->error("Connector '" . $connector->name . "' failed to stop: " . clean_error($@));
+ $logger->debug("Connector '" . $connector->name . "' failed to stop: $@");
+ }
+ }
+}
+
+sub reload {
+ my ($self) = @_;
+ $self->stop();
+ $self->{objects} = {};
+ $self->_load();
+}
+
+sub names {
+ my ($self) = @_;
+ return @{$self->{names}};
+}
+
+sub list {
+ my ($self) = @_;
+ $self->_load();
+ return sort { $a->name cmp $b->name } values %{$self->{objects}};
+}
+
+sub exists {
+ my ($self, $name) = @_;
+ $self->by_name($name) ? 1 : 0;
+}
+
+sub by_name {
+ my ($self, $name) = @_;
+ $self->_load();
+ return unless exists $self->{objects}->{$name};
+ return $self->{objects}->{$name};
+}
+
+1;
+
diff --git a/extensions/Push/lib/Constants.pm b/extensions/Push/lib/Constants.pm
new file mode 100644
index 000000000..18b12d511
--- /dev/null
+++ b/extensions/Push/lib/Constants.pm
@@ -0,0 +1,41 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Constants;
+
+use strict;
+use base 'Exporter';
+
+our @EXPORT = qw(
+ PUSH_RESULT_OK
+ PUSH_RESULT_IGNORED
+ PUSH_RESULT_TRANSIENT
+ PUSH_RESULT_ERROR
+ PUSH_RESULT_UNKNOWN
+ push_result_to_string
+
+ POLL_INTERVAL_SECONDS
+);
+
+use constant PUSH_RESULT_OK => 1;
+use constant PUSH_RESULT_IGNORED => 2;
+use constant PUSH_RESULT_TRANSIENT => 3;
+use constant PUSH_RESULT_ERROR => 4;
+use constant PUSH_RESULT_UNKNOWN => 5;
+
+sub push_result_to_string {
+ my ($result) = @_;
+ return 'OK' if $result == PUSH_RESULT_OK;
+ return 'OK-IGNORED' if $result == PUSH_RESULT_IGNORED;
+ return 'TRANSIENT-ERROR' if $result == PUSH_RESULT_TRANSIENT;
+ return 'FATAL-ERROR' if $result == PUSH_RESULT_ERROR;
+ return 'UNKNOWN' if $result == PUSH_RESULT_UNKNOWN;
+}
+
+use constant POLL_INTERVAL_SECONDS => 30;
+
+1;
diff --git a/extensions/Push/lib/Daemon.pm b/extensions/Push/lib/Daemon.pm
new file mode 100644
index 000000000..66e15783e
--- /dev/null
+++ b/extensions/Push/lib/Daemon.pm
@@ -0,0 +1,96 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Daemon;
+
+use strict;
+use warnings;
+
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Push;
+use Bugzilla::Extension::Push::Logger;
+use Carp qw(confess);
+use Daemon::Generic;
+use File::Basename;
+use Pod::Usage;
+
+sub start {
+ newdaemon();
+}
+
+#
+# daemon::generic config
+#
+
+sub gd_preconfig {
+ my $self = shift;
+ my $pidfile = $self->{gd_args}{pidfile};
+ if (!$pidfile) {
+ $pidfile = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".pid";
+ }
+ return (pidfile => $pidfile);
+}
+
+sub gd_getopt {
+ my $self = shift;
+ $self->SUPER::gd_getopt();
+ if ($self->{gd_args}{progname}) {
+ $self->{gd_progname} = $self->{gd_args}{progname};
+ } else {
+ $self->{gd_progname} = basename($0);
+ }
+ $self->{_original_zero} = $0;
+ $0 = $self->{gd_progname};
+}
+
+sub gd_postconfig {
+ my $self = shift;
+ $0 = delete $self->{_original_zero};
+}
+
+sub gd_more_opt {
+ my $self = shift;
+ return (
+ 'pidfile=s' => \$self->{gd_args}{pidfile},
+ 'n=s' => \$self->{gd_args}{progname},
+ );
+}
+
+sub gd_usage {
+ pod2usage({ -verbose => 0, -exitval => 'NOEXIT' });
+ return 0;
+};
+
+sub gd_redirect_output {
+ my $self = shift;
+
+ my $filename = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".log";
+ open(STDERR, ">>$filename") or (print "could not open stderr: $!" && exit(1));
+ close(STDOUT);
+ open(STDOUT, ">&STDERR") or die "redirect STDOUT -> STDERR: $!";
+ $SIG{HUP} = sub {
+ close(STDERR);
+ open(STDERR, ">>$filename") or (print "could not open stderr: $!" && exit(1));
+ };
+}
+
+sub gd_setup_signals {
+ my $self = shift;
+ $self->SUPER::gd_setup_signals();
+ $SIG{TERM} = sub { $self->gd_quit_event(); }
+}
+
+sub gd_run {
+ my $self = shift;
+ $::SIG{__DIE__} = \&Carp::confess if $self->{debug};
+ my $push = Bugzilla->push_ext;
+ $push->logger->{debug} = $self->{debug};
+ $push->is_daemon(1);
+ $push->start();
+}
+
+1;
diff --git a/extensions/Push/lib/Log.pm b/extensions/Push/lib/Log.pm
new file mode 100644
index 000000000..6faabea97
--- /dev/null
+++ b/extensions/Push/lib/Log.pm
@@ -0,0 +1,45 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Log;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Extension::Push::Message;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
+}
+
+sub count {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("SELECT COUNT(*) FROM push_log");
+}
+
+sub list {
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
+
+ my $ids = $dbh->selectcol_arrayref("
+ SELECT id
+ FROM push_log
+ ORDER BY processed_ts DESC " .
+ $dbh->sql_limit(100)
+ );
+ return Bugzilla::Extension::Push::LogEntry->new_from_list($ids);
+}
+
+1;
diff --git a/extensions/Push/lib/LogEntry.pm b/extensions/Push/lib/LogEntry.pm
new file mode 100644
index 000000000..303c19da4
--- /dev/null
+++ b/extensions/Push/lib/LogEntry.pm
@@ -0,0 +1,70 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::LogEntry;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Object';
+
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+
+use Bugzilla;
+use Bugzilla::Error;
+use Bugzilla::Extension::Push::Constants;
+
+#
+# initialisation
+#
+
+use constant DB_TABLE => 'push_log';
+use constant DB_COLUMNS => qw(
+ id
+ message_id
+ change_set
+ routing_key
+ connector
+ push_ts
+ processed_ts
+ result
+ data
+);
+use constant VALIDATORS => {
+ data => \&_check_data,
+};
+use constant NAME_FIELD => '';
+use constant LIST_ORDER => 'processed_ts DESC';
+
+#
+# accessors
+#
+
+sub message_id { return $_[0]->{'message_id'}; }
+sub change_set { return $_[0]->{'change_set'}; }
+sub routing_key { return $_[0]->{'routing_key'}; }
+sub connector { return $_[0]->{'connector'}; }
+sub push_ts { return $_[0]->{'push_ts'}; }
+sub processed_ts { return $_[0]->{'processed_ts'}; }
+sub result { return $_[0]->{'result'}; }
+sub data { return $_[0]->{'data'}; }
+
+sub result_string { return push_result_to_string($_[0]->result) }
+
+#
+# validators
+#
+
+sub _check_data {
+ my ($invocant, $value) = @_;
+ return $value eq '' ? undef : $value;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Logger.pm b/extensions/Push/lib/Logger.pm
new file mode 100644
index 000000000..68cec1e69
--- /dev/null
+++ b/extensions/Push/lib/Logger.pm
@@ -0,0 +1,70 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Logger;
+
+use strict;
+use warnings;
+
+use Apache2::Log;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::LogEntry;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
+}
+
+sub info { shift->_log_it('INFO', @_) }
+sub error { shift->_log_it('ERROR', @_) }
+sub debug { shift->_log_it('DEBUG', @_) }
+
+sub debugging {
+ my ($self) = @_;
+ return $self->{debug};
+}
+
+sub _log_it {
+ my ($self, $method, $message) = @_;
+ return if $method eq 'DEBUG' && !$self->debugging;
+ chomp $message;
+ if ($ENV{MOD_PERL}) {
+ Apache2::ServerRec::warn("Push $method: $message");
+ } elsif ($ENV{SCRIPT_FILENAME}) {
+ print STDERR "Push $method: $message\n";
+ } else {
+ print STDERR '[' . localtime(time) ."] $method: $message\n";
+ }
+}
+
+sub result {
+ my ($self, $connector, $message, $result, $data) = @_;
+ $data ||= '';
+
+ $self->info(sprintf(
+ "%s: Message #%s: %s %s",
+ $connector->name,
+ $message->message_id,
+ push_result_to_string($result),
+ $data
+ ));
+
+ Bugzilla::Extension::Push::LogEntry->create({
+ message_id => $message->message_id,
+ change_set => $message->change_set,
+ routing_key => $message->routing_key,
+ connector => $connector->name,
+ push_ts => $message->push_ts,
+ processed_ts => Bugzilla->dbh->selectrow_array('SELECT NOW()'),
+ result => $result,
+ data => $data,
+ });
+}
+
+1;
diff --git a/extensions/Push/lib/Message.pm b/extensions/Push/lib/Message.pm
new file mode 100644
index 000000000..ebe32d0ea
--- /dev/null
+++ b/extensions/Push/lib/Message.pm
@@ -0,0 +1,103 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Message;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Object';
+
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+
+use Bugzilla;
+use Bugzilla::Error;
+use Bugzilla::Extension::Push::Util;
+use Encode;
+
+#
+# initialisation
+#
+
+use constant DB_TABLE => 'push';
+use constant DB_COLUMNS => qw(
+ id
+ push_ts
+ payload
+ change_set
+ routing_key
+);
+use constant LIST_ORDER => 'push_ts';
+use constant VALIDATORS => {
+ push_ts => \&_check_push_ts,
+ payload => \&_check_payload,
+ change_set => \&_check_change_set,
+ routing_key => \&_check_routing_key,
+};
+
+# this creates an object which doesn't exist on the database
+sub new_transient {
+ my $invocant = shift;
+ my $class = ref($invocant) || $invocant;
+ my $object = shift;
+ bless($object, $class) if $object;
+ return $object;
+}
+
+# take a transient object and commit
+sub create_from_transient {
+ my ($self) = @_;
+ return $self->create($self);
+}
+
+#
+# accessors
+#
+
+sub push_ts { return $_[0]->{'push_ts'}; }
+sub payload { return $_[0]->{'payload'}; }
+sub change_set { return $_[0]->{'change_set'}; }
+sub routing_key { return $_[0]->{'routing_key'}; }
+sub message_id { return $_[0]->id; }
+
+sub payload_decoded {
+ my ($self) = @_;
+ return from_json($self->{'payload'});
+}
+
+#
+# validators
+#
+
+sub _check_push_ts {
+ my ($invocant, $value) = @_;
+ $value ||= Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ return $value;
+}
+
+sub _check_payload {
+ my ($invocant, $value) = @_;
+ length($value) || ThrowCodeError('push_invalid_payload');
+ return $value;
+}
+
+sub _check_change_set {
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value)) || ThrowCodeError('push_invalid_change_set');
+ return $value;
+}
+
+sub _check_routing_key {
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value)) || ThrowCodeError('push_invalid_routing_key');
+ return $value;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Option.pm b/extensions/Push/lib/Option.pm
new file mode 100644
index 000000000..25d529f98
--- /dev/null
+++ b/extensions/Push/lib/Option.pm
@@ -0,0 +1,66 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Option;
+
+use strict;
+use warnings;
+
+use base 'Bugzilla::Object';
+
+use Bugzilla;
+use Bugzilla::Error;
+use Bugzilla::Util;
+
+#
+# initialisation
+#
+
+use constant DB_TABLE => 'push_options';
+use constant DB_COLUMNS => qw(
+ id
+ connector
+ option_name
+ option_value
+);
+use constant UPDATE_COLUMNS => qw(
+ option_value
+);
+use constant VALIDATORS => {
+ connector => \&_check_connector,
+};
+use constant LIST_ORDER => 'connector';
+
+#
+# accessors
+#
+
+sub connector { return $_[0]->{'connector'}; }
+sub name { return $_[0]->{'option_name'}; }
+sub value { return $_[0]->{'option_value'}; }
+
+#
+# mutators
+#
+
+sub set_value { $_[0]->{'option_value'} = $_[1]; }
+
+#
+# validators
+#
+
+sub _check_connector {
+ my ($invocant, $value) = @_;
+ $value eq '*'
+ || $value eq 'global'
+ || Bugzilla->push_ext->connectors->exists($value)
+ || ThrowCodeError('push_invalid_connector');
+ return $value;
+}
+
+1;
+
diff --git a/extensions/Push/lib/Push.pm b/extensions/Push/lib/Push.pm
new file mode 100644
index 000000000..aaac0bbd6
--- /dev/null
+++ b/extensions/Push/lib/Push.pm
@@ -0,0 +1,264 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Push;
+
+use strict;
+use warnings;
+
+use Bugzilla::Extension::Push::BacklogMessage;
+use Bugzilla::Extension::Push::Config;
+use Bugzilla::Extension::Push::Connectors;
+use Bugzilla::Extension::Push::Constants;
+use Bugzilla::Extension::Push::Log;
+use Bugzilla::Extension::Push::Logger;
+use Bugzilla::Extension::Push::Message;
+use Bugzilla::Extension::Push::Option;
+use Bugzilla::Extension::Push::Queue;
+use Bugzilla::Extension::Push::Util;
+use DateTime;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ $self->{is_daemon} = 0;
+ return $self;
+}
+
+sub is_daemon {
+ my ($self, $value) = @_;
+ if (defined $value) {
+ $self->{is_daemon} = $value ? 1 : 0;
+ }
+ return $self->{is_daemon};
+}
+
+sub start {
+ my ($self) = @_;
+ my $connectors = $self->connectors;
+ $self->{config_last_modified} = $self->get_config_last_modified();
+ $self->{config_last_checked} = (time);
+
+ foreach my $connector ($connectors->list) {
+ $connector->backlog->reset_backoff();
+ }
+
+ while(1) {
+ if ($self->_dbh_check()) {
+ $self->_reload();
+ $self->push();
+ }
+ sleep(POLL_INTERVAL_SECONDS);
+ }
+}
+
+sub push {
+ my ($self) = @_;
+ my $logger = $self->logger;
+ my $connectors = $self->connectors;
+
+ my $enabled = 0;
+ foreach my $connector ($connectors->list) {
+ if ($connector->enabled) {
+ $enabled = 1;
+ last;
+ }
+ }
+ return unless $enabled;
+
+ $logger->debug("polling");
+
+ # process each message
+ while(my $message = $self->queue->oldest) {
+ foreach my $connector ($connectors->list) {
+ next unless $connector->enabled;
+ next unless $connector->should_send($message);
+ $logger->debug("pushing to " . $connector->name);
+
+ my $is_backlogged = $connector->backlog->count;
+
+ if (!$is_backlogged) {
+ # connector isn't backlogged, immediate send
+ $logger->debug("immediate send");
+ my ($result, $data);
+ eval {
+ ($result, $data) = $connector->send($message);
+ };
+ if ($@) {
+ $result = PUSH_RESULT_TRANSIENT;
+ $data = clean_error($@);
+ }
+ if (!$result) {
+ $logger->error($connector->name . " failed to return a result code");
+ $result = PUSH_RESULT_UNKNOWN;
+ }
+ $logger->result($connector, $message, $result, $data);
+
+ if ($result == PUSH_RESULT_TRANSIENT) {
+ $is_backlogged = 1;
+ }
+ }
+
+ # if the connector is backlogged, push to the backlog queue
+ if ($is_backlogged) {
+ $logger->debug("backlogged");
+ my $backlog = Bugzilla::Extension::Push::BacklogMessage->create_from_message($message, $connector);
+ }
+ }
+
+ # message processed
+ $message->remove_from_db();
+ }
+
+ # process backlog
+ foreach my $connector ($connectors->list) {
+ next unless $connector->enabled;
+ my $message = $connector->backlog->oldest();
+ next unless $message;
+
+ $logger->debug("processing backlog for " . $connector->name);
+ while ($message) {
+ my ($result, $data);
+ eval {
+ ($result, $data) = $connector->send($message);
+ };
+ if ($@) {
+ $result = PUSH_RESULT_TRANSIENT;
+ $data = $@;
+ }
+ $message->inc_attempts($result == PUSH_RESULT_OK ? '' : $data);
+ if (!$result) {
+ $logger->error($connector->name . " failed to return a result code");
+ $result = PUSH_RESULT_UNKNOWN;
+ }
+ $logger->result($connector, $message, $result, $data);
+
+ if ($result == PUSH_RESULT_TRANSIENT) {
+ # connector is still down, stop trying
+ $connector->backlog->inc_backoff();
+ last;
+ }
+
+ # message was processed
+ $message->remove_from_db();
+
+ $message = $connector->backlog->oldest();
+ }
+ }
+}
+
+sub _reload {
+ my ($self) = @_;
+
+ # check for updated config every 60 seconds
+ my $now = (time);
+ if ($now - $self->{config_last_checked} < 60) {
+ return;
+ }
+ $self->{config_last_checked} = $now;
+
+ $self->logger->debug('Checking for updated configuration');
+ if ($self->get_config_last_modified eq $self->{config_last_modified}) {
+ return;
+ }
+ $self->{config_last_modified} = $self->get_config_last_modified();
+
+ $self->logger->debug('Configuration has been updated');
+ $self->connectors->reload();
+}
+
+sub get_config_last_modified {
+ my ($self) = @_;
+ my $options_list = Bugzilla::Extension::Push::Option->match({
+ connector => '*',
+ option_name => 'last-modified',
+ });
+ if (@$options_list) {
+ return $options_list->[0]->value;
+ } else {
+ return $self->set_config_last_modified();
+ }
+}
+
+sub set_config_last_modified {
+ my ($self) = @_;
+ my $options_list = Bugzilla::Extension::Push::Option->match({
+ connector => '*',
+ option_name => 'last-modified',
+ });
+ my $now = DateTime->now->datetime();
+ if (@$options_list) {
+ $options_list->[0]->set_value($now);
+ $options_list->[0]->update();
+ } else {
+ Bugzilla::Extension::Push::Option->create({
+ connector => '*',
+ option_name => 'last-modified',
+ option_value => $now,
+ });
+ }
+ return $now;
+}
+
+sub config {
+ my ($self) = @_;
+ if (!$self->{config}) {
+ $self->{config} = Bugzilla::Extension::Push::Config->new(
+ 'global',
+ {
+ name => 'log_purge',
+ label => 'Purge logs older than (days)',
+ type => 'string',
+ default => '7',
+ required => '1',
+ validate => sub { $_[0] =~ /\D/ && die "Invalid purge duration (must be numeric)\n"; },
+ },
+ );
+ $self->{config}->load();
+ }
+ return $self->{config};
+}
+
+sub logger {
+ my ($self, $value) = @_;
+ $self->{logger} = $value if $value;
+ return $self->{logger};
+}
+
+sub connectors {
+ my ($self, $value) = @_;
+ $self->{connectors} = $value if $value;
+ return $self->{connectors};
+}
+
+sub queue {
+ my ($self) = @_;
+ $self->{queue} ||= Bugzilla::Extension::Push::Queue->new();
+ return $self->{queue};
+}
+
+sub log {
+ my ($self) = @_;
+ $self->{log} ||= Bugzilla::Extension::Push::Log->new();
+ return $self->{log};
+}
+
+sub _dbh_check {
+ my ($self) = @_;
+ eval {
+ Bugzilla->dbh->selectrow_array("SELECT 1 FROM push");
+ };
+ if ($@) {
+ $self->logger->error(clean_error($@));
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+1;
diff --git a/extensions/Push/lib/Queue.pm b/extensions/Push/lib/Queue.pm
new file mode 100644
index 000000000..d89cb23c3
--- /dev/null
+++ b/extensions/Push/lib/Queue.pm
@@ -0,0 +1,72 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Queue;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Extension::Push::Message;
+
+sub new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
+}
+
+sub count {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("SELECT COUNT(*) FROM push");
+}
+
+sub oldest {
+ my ($self) = @_;
+ my @messages = $self->list(limit => 1);
+ return scalar(@messages) ? $messages[0] : undef;
+}
+
+sub by_id {
+ my ($self, $id) = @_;
+ my @messages = $self->list(
+ limit => 1,
+ filter => "AND (push.id = $id)",
+ );
+ return scalar(@messages) ? $messages[0] : undef;
+}
+
+sub list {
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
+
+ my $sth = $dbh->prepare("
+ SELECT id, push_ts, payload, change_set, routing_key
+ FROM push
+ WHERE (1 = 1) " .
+ $args{filter} . "
+ ORDER BY push_ts " .
+ $dbh->sql_limit($args{limit})
+ );
+ $sth->execute();
+ while (my $row = $sth->fetchrow_hashref()) {
+ push @result, Bugzilla::Extension::Push::Message->new({
+ id => $row->{id},
+ push_ts => $row->{push_ts},
+ payload => $row->{payload},
+ change_set => $row->{change_set},
+ routing_key => $row->{routing_key},
+ });
+ }
+ return @result;
+}
+
+1;
diff --git a/extensions/Push/lib/Serialise.pm b/extensions/Push/lib/Serialise.pm
new file mode 100644
index 000000000..82eb654b5
--- /dev/null
+++ b/extensions/Push/lib/Serialise.pm
@@ -0,0 +1,322 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Serialise;
+
+use strict;
+use warnings;
+
+use Bugzilla::Constants;
+use Bugzilla::Extension::Push::Util;
+use Bugzilla::Version;
+
+use Scalar::Util 'blessed';
+use JSON ();
+
+my $_instance;
+sub instance {
+ $_instance ||= Bugzilla::Extension::Push::Serialise->_new();
+ return $_instance;
+}
+
+sub _new {
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
+}
+
+# given an object, serliase to a hash
+sub object_to_hash {
+ my ($self, $object, $is_shallow) = @_;
+
+ my $method = lc(blessed($object));
+ $method =~ s/::/_/g;
+ $method =~ s/^bugzilla//;
+ return unless $self->can($method);
+ (my $name = $method) =~ s/^_//;
+
+ # check for a cached hash
+ my $cache = Bugzilla->request_cache;
+ my $cache_id = "push." . ($is_shallow ? 'shallow.' : 'deep.') . $object;
+ if (exists($cache->{$cache_id})) {
+ return wantarray ? ($cache->{$cache_id}, $name) : $cache->{$cache_id};
+ }
+
+ # call the right method to serialise to a hash
+ my $rh = $self->$method($object, $is_shallow);
+
+ # store in cache
+ if ($cache_id) {
+ $cache->{$cache_id} = $rh;
+ }
+
+ return wantarray ? ($rh, $name) : $rh;
+}
+
+# given a changes hash, return an event hash
+sub changes_to_event {
+ my ($self, $changes) = @_;
+
+ my $event = {};
+
+ # create common (created and modified) fields
+ $event->{'user'} = $self->object_to_hash(Bugzilla->user);
+ my $timestamp =
+ $changes->{'timestamp'}
+ || Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+ $event->{'time'} = datetime_to_timestamp($timestamp);
+
+ foreach my $change (@{$changes->{'changes'}}) {
+ if (exists $change->{'field'}) {
+ # map undef to emtpy
+ hash_undef_to_empty($change);
+
+ # custom_fields change from undef to empty, ignore these changes
+ return if ($change->{'added'} || "") eq "" &&
+ ($change->{'removed'} || "") eq "";
+
+ # use saner field serialisation
+ my $field = $change->{'field'};
+ $change->{'field'} = $field;
+
+ if ($field eq 'priority' || $field eq 'target_milestone') {
+ $change->{'added'} = _select($change->{'added'});
+ $change->{'removed'} = _select($change->{'removed'});
+
+ } elsif ($field =~ /^cf_/) {
+ $change->{'added'} = _custom_field($field, $change->{'added'});
+ $change->{'removed'} = _custom_field($field, $change->{'removed'});
+ }
+
+ $event->{'changes'} = [] unless exists $event->{'changes'};
+ push @{$event->{'changes'}}, $change;
+ }
+ }
+
+ return $event;
+}
+
+# bugzilla returns '---' or '--' for single-select fields that have no value
+# selected. it makes more sense to return an empty string.
+sub _select {
+ my ($value) = @_;
+ return '' if $value eq '---' or $value eq '--';
+ return $value;
+}
+
+# return an object which serialises to a json boolean, but still acts as a perl
+# boolean
+sub _boolean {
+ my ($value) = @_;
+ return $value ? JSON::true : JSON::false;
+}
+
+sub _string {
+ my ($value) = @_;
+ return defined($value) ? $value : '';
+}
+
+sub _time {
+ my ($value) = @_;
+ return defined($value) ? datetime_to_timestamp($value) : undef;
+}
+
+sub _integer {
+ my ($value) = @_;
+ return defined($value) ? $value + 0 : undef;
+}
+
+sub _array {
+ my ($value) = @_;
+ return defined($value) ? $value : [];
+}
+
+sub _custom_field {
+ my ($field, $value) = @_;
+ $field = Bugzilla::Field->new({ name => $field }) unless blessed $field;
+
+ if ($field->type == FIELD_TYPE_DATETIME) {
+ return _time($value);
+
+ } elsif ($field->type == FIELD_TYPE_SINGLE_SELECT) {
+ return _select($value);
+
+ } elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
+ return _array($value);
+
+ } else {
+ return _string($value);
+ }
+}
+
+#
+# class mappings
+# automatically derrived from the class name
+# Bugzilla::Bug --> _bug, Bugzilla::User --> _user, etc
+#
+
+sub _bug {
+ my ($self, $bug) = @_;
+
+ my $version = $bug->can('version_obj')
+ ? $bug->version_obj
+ : Bugzilla::Version->new({ name => $bug->version, product => $bug->product_obj });
+
+ my $milestone;
+ if (_select($bug->target_milestone) ne '') {
+ $milestone = $bug->can('target_milestone_obj')
+ ? $bug->target_milestone_obj
+ : Bugzilla::Milestone->new({ name => $bug->target_milestone, product => $bug->product_obj });
+ }
+
+ my $status = $bug->can('status_obj')
+ ? $bug->status_obj
+ : Bugzilla::Status->new({ name => $bug->bug_status });
+
+ my $rh = {
+ id => _integer($bug->bug_id),
+ alias => _string($bug->alias),
+ assigned_to => $self->_user($bug->assigned_to),
+ classification => _string($bug->classification),
+ component => $self->_component($bug->component_obj),
+ creation_time => _time($bug->creation_ts || $bug->delta_ts),
+ flags => (mapr { $self->_flag($_) } $bug->flags),
+ is_private => _boolean(!is_public($bug)),
+ keywords => (mapr { _string($_->name) } $bug->keyword_objects),
+ last_change_time => _time($bug->delta_ts),
+ operating_system => _string($bug->op_sys),
+ platform => _string($bug->rep_platform),
+ priority => _select($bug->priority),
+ product => $self->_product($bug->product_obj),
+ qa_contact => $self->_user($bug->qa_contact),
+ reporter => $self->_user($bug->reporter),
+ resolution => _string($bug->resolution),
+ severity => _string($bug->bug_severity),
+ status => $self->_status($status),
+ summary => _string($bug->short_desc),
+ target_milestone => $self->_milestone($milestone),
+ url => _string($bug->bug_file_loc),
+ version => $self->_version($version),
+ whiteboard => _string($bug->status_whiteboard),
+ };
+
+ # add custom fields
+ my @custom_fields = Bugzilla->active_custom_fields;
+ foreach my $field (@custom_fields) {
+ my $name = $field->name;
+
+ # skip custom fields that are hidded from this product/component
+ next if Bugzilla::Extension::BMO::cf_hidden_in_product(
+ $name, $bug->product, $bug->component);
+
+ $rh->{$name} = _custom_field($field, $bug->$name);
+ }
+
+ return $rh;
+}
+
+sub _user {
+ my ($self, $user) = @_;
+ return undef unless $user;
+ return {
+ id => _integer($user->id),
+ login => _string($user->login),
+ real_name => _string($user->name),
+ };
+}
+
+sub _component {
+ my ($self, $component) = @_;
+ return {
+ id => _integer($component->id),
+ name => _string($component->name),
+ };
+}
+
+sub _attachment {
+ my ($self, $attachment, $is_shallow) = @_;
+ my $rh = {
+ id => _integer($attachment->id),
+ content_type => _string($attachment->contenttype),
+ creation_time => _time($attachment->attached),
+ description => _string($attachment->description),
+ file_name => _string($attachment->filename),
+ flags => (mapr { $self->_flag($_) } $attachment->flags),
+ is_obsolete => _boolean($attachment->isobsolete),
+ is_patch => _boolean($attachment->ispatch),
+ is_private => _boolean(!is_public($attachment)),
+ last_change_time => _time($attachment->modification_time),
+ };
+ if (!$is_shallow) {
+ $rh->{bug} = $self->_bug($attachment->bug);
+ }
+ return $rh;
+}
+
+sub _comment {
+ my ($self, $comment, $is_shallow) = @_;
+ my $rh = {
+ id => _integer($comment->bug_id),
+ body => _string($comment->body),
+ creation_time => _time($comment->creation_ts),
+ is_private => _boolean($comment->is_private),
+ number => _integer($comment->count),
+ };
+ if (!$is_shallow) {
+ $rh->{bug} = $self->_bug($comment->bug);
+ }
+ return $rh;
+}
+
+sub _product {
+ my ($self, $product) = @_;
+ return {
+ id => _integer($product->id),
+ name => _string($product->name),
+ };
+}
+
+sub _flag {
+ my ($self, $flag) = @_;
+ my $rh = {
+ id => _integer($flag->id),
+ name => _string($flag->type->name),
+ value => _string($flag->status),
+ };
+ if ($flag->requestee) {
+ $rh->{'requestee'} = $self->_user($flag->requestee);
+ }
+ return $rh;
+}
+
+sub _version {
+ my ($self, $version) = @_;
+ return {
+ id => _integer($version->id),
+ name => _string($version->name),
+ };
+}
+
+sub _milestone {
+ my ($self, $milestone) = @_;
+ return undef unless $milestone;
+ return {
+ id => _integer($milestone->id),
+ name => _string($milestone->name),
+ };
+}
+
+sub _status {
+ my ($self, $status) = @_;
+ return {
+ id => _integer($status->id),
+ name => _string($status->name),
+ };
+}
+
+1;
diff --git a/extensions/Push/lib/Util.pm b/extensions/Push/lib/Util.pm
new file mode 100644
index 000000000..f52db6936
--- /dev/null
+++ b/extensions/Push/lib/Util.pm
@@ -0,0 +1,162 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::Push::Util;
+
+use strict;
+use warnings;
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util qw(datetime_from trim);
+use Data::Dumper;
+use Encode;
+use JSON ();
+use Scalar::Util qw(blessed);
+use Time::HiRes;
+
+use base qw(Exporter);
+our @EXPORT = qw(
+ datetime_to_timestamp
+ debug_dump
+ get_first_value
+ hash_undef_to_empty
+ is_public
+ mapr
+ clean_error
+ change_set_id
+ canon_email
+ to_json from_json
+);
+
+# returns true if the specified object is public
+sub is_public {
+ my ($object) = @_;
+
+ my $default_user = Bugzilla::User->new();
+
+ if ($object->isa('Bugzilla::Bug')) {
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
+
+ } elsif ($object->isa('Bugzilla::Comment')) {
+ return if $object->is_private;
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
+
+ } elsif ($object->isa('Bugzilla::Attachment')) {
+ return if $object->isprivate;
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
+
+ } else {
+ warn "Unsupported class " . blessed($object) . " passed to is_public()\n";
+ }
+
+ return 1;
+}
+
+# return the first existing value from the hashref for the given list of keys
+sub get_first_value {
+ my ($rh, @keys) = @_;
+ foreach my $field (@keys) {
+ return $rh->{$field} if exists $rh->{$field};
+ }
+ return;
+}
+
+# wrapper for map that works on array references
+sub mapr(&$) {
+ my ($filter, $ra) = @_;
+ my @result = map(&$filter, @$ra);
+ return \@result;
+}
+
+
+# convert datetime string (from db) to a UTC json friendly datetime
+sub datetime_to_timestamp {
+ my ($datetime_string) = @_;
+ return '' unless $datetime_string;
+ return datetime_from($datetime_string, 'UTC')->datetime();
+}
+
+# replaces all undef values in a hashref with an empty string (deep)
+sub hash_undef_to_empty {
+ my ($rh) = @_;
+ foreach my $key (keys %$rh) {
+ my $value = $rh->{$key};
+ if (!defined($value)) {
+ $rh->{$key} = '';
+ } elsif (ref($value) eq 'HASH') {
+ hash_undef_to_empty($value);
+ }
+ }
+}
+
+# debugging methods
+sub debug_dump {
+ my ($object) = @_;
+ local $Data::Dumper::Sortkeys = 1;
+ my $output = Dumper($object);
+ $output =~ s/</&lt;/g;
+ print "<pre>$output</pre>";
+}
+
+# removes stacktrace and "at /some/path ..." from errors
+sub clean_error {
+ my ($error) = @_;
+ my $path = bz_locations->{'extensionsdir'};
+ $error = $1 if $error =~ /^(.+?) at \Q$path/s;
+ $path = '/loader/0x';
+ $error = $1 if $error =~ /^(.+?) at \Q$path/s;
+ $error =~ s/(^\s+|\s+$)//g;
+ return $error;
+}
+
+# generate a new change_set id
+sub change_set_id {
+ return "$$." . Time::HiRes::time();
+}
+
+# remove guff from email addresses
+sub clean_email {
+ my $email = shift;
+ $email = trim($email);
+ $email = $1 if $email =~ /^(\S+)/;
+ $email =~ s/&#64;/@/;
+ $email = lc $email;
+ return $email;
+}
+
+# resolve to canonised email form
+# eg. glob+bmo@mozilla.com --> glob@mozilla.com
+sub canon_email {
+ my $email = shift;
+ $email = clean_email($email);
+ $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/;
+ return $email;
+}
+
+# json helpers
+sub to_json {
+ my ($object, $pretty) = @_;
+ if ($pretty) {
+ return decode('utf8', JSON->new->utf8(1)->pretty(1)->encode($object));
+ } else {
+ return JSON->new->ascii(1)->shrink(1)->encode($object);
+ }
+}
+
+sub from_json {
+ my ($json) = @_;
+ if (utf8::is_utf8($json)) {
+ $json = encode('utf8', $json);
+ }
+ return JSON->new->utf8(1)->decode($json);
+}
+
+1;
diff --git a/extensions/Push/template/en/default/hook/admin/admin-end_links_right.html.tmpl b/extensions/Push/template/en/default/hook/admin/admin-end_links_right.html.tmpl
new file mode 100644
index 000000000..78e314ab2
--- /dev/null
+++ b/extensions/Push/template/en/default/hook/admin/admin-end_links_right.html.tmpl
@@ -0,0 +1,18 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.in_group('admin') %]
+ <dt id="push">
+ Push
+ </dt>
+ <dd>
+ <a href="page.cgi?id=push_config.html">Configuration</a><br>
+ <a href="page.cgi?id=push_queues.html">Queues</a><br>
+ <a href="page.cgi?id=push_log.html">Log</a><br>
+ </dd>
+[% END %]
diff --git a/extensions/Push/template/en/default/hook/global/code-error-errors.html.tmpl b/extensions/Push/template/en/default/hook/global/code-error-errors.html.tmpl
new file mode 100644
index 000000000..515f00fa8
--- /dev/null
+++ b/extensions/Push/template/en/default/hook/global/code-error-errors.html.tmpl
@@ -0,0 +1,25 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "push_invalid_payload" %]
+ [% title = "Invalid payload" %]
+ An invalid or empty payload was passed to Push.
+
+[% ELSIF error == "push_invalid_change_set" %]
+ [% title = "Invalid change_set" %]
+ An invalid or empty change_set was passed to Push.
+
+[% ELSIF error == "push_invalid_routing_key" %]
+ [% title = "Invalid routing_key" %]
+ An invalid or empty routing_key was passed to Push.
+
+[% ELSIF error == "push_invalid_connector" %]
+ [% title = "Invalid connector" %]
+ An invalid connector was passed to Push.
+
+[% END %]
diff --git a/extensions/Push/template/en/default/hook/global/messages-messages.html.tmpl b/extensions/Push/template/en/default/hook/global/messages-messages.html.tmpl
new file mode 100644
index 000000000..e4a016aee
--- /dev/null
+++ b/extensions/Push/template/en/default/hook/global/messages-messages.html.tmpl
@@ -0,0 +1,16 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF message_tag == "push_config_updated" %]
+ Changes to the configuration have been saved.
+ Please allow up to 60 seconds for the change to be active.
+
+[% ELSIF message_tag == "push_message_deleted" %]
+ The message has been deleted.
+
+[% END %]
diff --git a/extensions/Push/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/Push/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..2b8a1c4e0
--- /dev/null
+++ b/extensions/Push/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "push_error" %]
+ [% error_message FILTER html %]
+[% END %]
diff --git a/extensions/Push/template/en/default/pages/push_config.html.tmpl b/extensions/Push/template/en/default/pages/push_config.html.tmpl
new file mode 100644
index 000000000..6e6507a39
--- /dev/null
+++ b/extensions/Push/template/en/default/pages/push_config.html.tmpl
@@ -0,0 +1,134 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Push Administration: Configuration"
+ javascript_urls = [ 'extensions/Push/web/admin.js' ]
+ style_urls = [ 'extensions/Push/web/admin.css' ]
+%]
+
+<script>
+var push_defaults = new Array();
+[% FOREACH option = push.config.options %]
+ [% IF option.name != 'enabled' && option.default != '' %]
+ push_defaults['global_[% option.name FILTER js %]'] = '[% option.default FILTER js %]';
+ [% END %]
+[% END %]
+[% FOREACH connector = connectors.list %]
+ [% FOREACH option = connector.config.options %]
+ [% IF option.name != 'enabled' && option.default != '' %]
+ push_defaults['[% connector.name FILTER js %]_[% option.name FILTER js %]'] = '[% option.default FILTER js %]';
+ [% END %]
+ [% END %]
+[% END %]
+</script>
+
+<form method="POST" action="page.cgi">
+<input type="hidden" name="id" value="push_config.html">
+<input type="hidden" name="save" value="1">
+
+<table border="0" cellspacing="0" cellpadding="5" width="100%">
+
+[% PROCESS options
+ name = 'global',
+ config = push.config
+%]
+
+[% FOREACH connector = connectors.list %]
+ [% PROCESS options
+ name = connector.name
+ config = connector.config
+ %]
+[% END %]
+
+<tr>
+ <td>&nbsp;</td>
+ <td colspan="2"><hr></td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td colspan="2">
+ <input type="submit" value="Submit Changes">
+ <input type="submit" value="Reset to Defaults" onclick="reset_to_defaults(); return false">
+ </td>
+</tr>
+
+
+<tr>
+ <td style="min-width: 10em">&nbsp;</td>
+ <td>&nbsp;</td>
+ <td width="100%">&nbsp;</td>
+</tr>
+
+</table>
+
+</form>
+
+[% INCLUDE global/footer.html.tmpl %]
+
+[% BLOCK options %]
+ <tr class="connector">
+ <th>[% name FILTER ucfirst FILTER html %]</th>
+ <td colspan="2"><hr></td>
+ </tr>
+ [% FOREACH option = config.options %]
+ [% class = name _ '_tr' IF option.name != 'enabled' %]
+ <tr class="[% class FILTER html %] option">
+ <th>
+ [% IF option.required %]
+ <span class="required_option" title="Mandatory option">*</span>&nbsp;
+ [% END %]
+ [% option.label FILTER html %]
+ </th>
+ <td>
+ [% IF option.type == 'string' %]
+ <input type="text" name="[% name FILTER html %].[% option.name FILTER html %]"
+ value="[% config.${option.name} FILTER html %]" size="60"
+ id="[% name FILTER html %]_[% option.name FILTER html %]">
+
+ [% ELSIF option.type == 'password' %]
+ <input type="password" name="[% name FILTER html %].[% option.name FILTER html %]"
+ value="[% config.${option.name} FILTER html %]" size="60"
+ id="[% name FILTER html %]_[% option.name FILTER html %]">
+
+ [% ELSIF option.type == 'select' %]
+ <select name="[% name FILTER html %].[% option.name FILTER html %]"
+ id="[% name FILTER html %]_[% option.name FILTER html %]"
+ [% IF option.name == 'enabled' && name != 'global' %]
+ onchange="toggle_options(this.value == 'Enabled', '[% name FILTER js %]')"
+ [% END %]
+ >
+ [% IF option.name != 'enabled' && !option.required %]
+ <option value="""
+ [% ' selected' IF config.${option.name} == "" %]></option>
+ [% END %]
+ [% FOREACH value = option.values %]
+ <option value="[% value FILTER html %]"
+ [% ' selected' IF config.${option.name} == value %]>[% value FILTER html %]</option>
+ [% END %]
+ </select>
+
+ [% ELSE %]
+ unsupported option type '[% option.type FILTER html %]'
+ [% END %]
+ </td>
+ [% IF option.help %]
+ <td class="help">[% option.help FILTER html %]</td>
+ [% ELSE %]
+ <td>&nbsp;</td>
+ [% END %]
+ </tr>
+ [% END %]
+ [% IF name != 'global' %]
+ <script>
+ var is_enabled = document.getElementById('[% name FILTER js %]_enabled').value == 'Enabled';
+ toggle_options(is_enabled, '[% name FILTER js %]');
+ </script>
+ [% END %]
+[% END %]
diff --git a/extensions/Push/template/en/default/pages/push_log.html.tmpl b/extensions/Push/template/en/default/pages/push_log.html.tmpl
new file mode 100644
index 000000000..a51cb22cf
--- /dev/null
+++ b/extensions/Push/template/en/default/pages/push_log.html.tmpl
@@ -0,0 +1,45 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Push Administration: Logs"
+ javascript_urls = [ 'extensions/Push/web/admin.js' ]
+ style_urls = [ 'extensions/Push/web/admin.css' ]
+%]
+[% logs = push.log %]
+
+<table id="report" cellspacing="0">
+
+[% IF logs.count %]
+ <tr class="report-subheader">
+ <th nowrap>Connector</th>
+ <th nowrap>Event Timestamp</th>
+ <th nowrap>Processed Timestamp</th>
+ <th nowrap>Status</th>
+ <th nowrap>Message</th>
+ </tr>
+[% END %]
+
+[% FOREACH log = logs.list %]
+ <tr class="row [% loop.count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td nowrap>[% log.connector FILTER html %]</td>
+ <td nowrap>[% log.push_ts FILTER time FILTER html %]</td>
+ <td nowrap>[% log.processed_ts FILTER time FILTER html %]</td>
+ <td nowrap>[% log.result_string FILTER html %]</td>
+ <td>[% log.data FILTER html %]</td>
+ </tr>
+[% END %]
+
+<tr>
+ <td colspan="5">&nbsp;</td>
+</tr>
+
+</table>
+
+[% INCLUDE global/footer.html.tmpl %]
+
diff --git a/extensions/Push/template/en/default/pages/push_queues.html.tmpl b/extensions/Push/template/en/default/pages/push_queues.html.tmpl
new file mode 100644
index 000000000..d1985c89a
--- /dev/null
+++ b/extensions/Push/template/en/default/pages/push_queues.html.tmpl
@@ -0,0 +1,102 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Push Administration: Queues"
+ javascript_urls = [ 'extensions/Push/web/admin.js' ]
+ style_urls = [ 'extensions/Push/web/admin.css' ]
+%]
+
+<table id="report" cellspacing="0">
+
+[% PROCESS show_queue
+ queue = push.queue
+ title = 'Pending'
+ pending = 1
+%]
+
+[% FOREACH connector = push.connectors.list %]
+ [% NEXT UNLESS connector.enabled %]
+ [% PROCESS show_queue
+ queue = connector.backlog
+ title = connector.name _ ' Backlog'
+ pending = 0
+ %]
+[% END %]
+
+</table>
+
+[% INCLUDE global/footer.html.tmpl %]
+
+[% BLOCK show_queue %]
+ [% count = queue.count %]
+ <tr class="report-header">
+ <th colspan="2">
+ [% title FILTER html %] Queue ([% count FILTER html %])
+ </th>
+ [% IF queue.backoff && count %]
+ <th class="rhs" colspan="5">
+ Next Attempt: [% queue.backoff.next_attempt_ts FILTER time %]
+ </th>
+ [% ELSE %]
+ <th colspan="5">&nbsp;</td>
+ [% END %]
+ </tr>
+
+ [% IF count %]
+ <tr class="report-subheader">
+ <th nowrap>Timestamp</th>
+ <th nowrap>Change Set</th>
+ [% IF pending %]
+ <th nowrap colspan="4">Routing Key</th>
+ [% ELSE %]
+ <th nowrap>Routing Key</th>
+ <th nowrap>Last Attempt</th>
+ <th nowrap>Attempts</th>
+ <th nowrap>Last Error</th>
+ [% END %]
+ <th>&nbsp;</th>
+ </tr>
+ [% END %]
+
+ [% FOREACH message = queue.list('limit', 10) %]
+ <tr class="row [% loop.count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td nowrap>[% message.push_ts FILTER html %]</td>
+ <td nowrap>[% message.change_set FILTER html %]</td>
+ [% IF pending %]
+ <td nowrap colspan="4">[% message.routing_key FILTER html %]</td>
+ [% ELSE %]
+ <td nowrap>[% message.routing_key FILTER html %]</td>
+ [% IF message.attempt_ts %]
+ <td nowrap>[% message.attempt_ts FILTER time %]</td>
+ <td nowrap>[% message.attempts FILTER html %]</td>
+ <td width="100%">
+ [% IF message.last_error.length > 40 %]
+ [% last_error = message.last_error.substr(0, 40) _ '...' %]
+ [% ELSE %]
+ [% last_error = message.last_error %]
+ [% END %]
+ [% last_error FILTER html %]</td>
+ [% ELSE %]
+ <td>-</td>
+ <td>-</td>
+ <td width="100%">-</td>
+ [% END %]
+ [% END %]
+ <td class="rhs">
+ <a href="?id=push_queues_view.html&amp;[% ~%]
+ message=[% message.id FILTER uri %]&amp;[% ~%]
+ connector=[% queue.connector FILTER uri %]">View</a>
+ </td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <td colspan="7">&nbsp;</td>
+ </tr>
+[% END %]
diff --git a/extensions/Push/template/en/default/pages/push_queues_view.html.tmpl b/extensions/Push/template/en/default/pages/push_queues_view.html.tmpl
new file mode 100644
index 000000000..6330d8ae4
--- /dev/null
+++ b/extensions/Push/template/en/default/pages/push_queues_view.html.tmpl
@@ -0,0 +1,80 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Push Administration: Queues: Payload"
+ javascript_urls = [ 'extensions/Push/web/admin.js' ]
+ style_urls = [ 'extensions/Push/web/admin.css' ]
+%]
+
+[% IF !message_obj %]
+ <a href="?id=push_queues.html">Return</a>
+ [% RETURN %]
+[% END %]
+
+<table id="report" cellspacing="0">
+
+<tr>
+ <th class="report-header" nowrap>Connector</th>
+ <td width="100%">[% message_obj.connector || '-' FILTER html %]</td>
+</tr>
+<tr>
+ <th class="report-header" nowrap>Message ID</th>
+ <td width="100%">[% message_obj.message_id FILTER html %]</td>
+</tr>
+<tr>
+ <th class="report-header" nowrap>Push Time</th>
+ <td width="100%">[% message_obj.push_ts FILTER time FILTER html %]</td>
+</tr>
+<tr>
+ <th class="report-header" nowrap>Change Set</th>
+ <td width="100%">[% message_obj.change_set FILTER html %]</td>
+</tr>
+<tr>
+ <th class="report-header" nowrap>Routing Key</th>
+ <td width="100%">[% message_obj.routing_key FILTER html %]</td>
+</tr>
+
+[% IF message_obj.attempts %]
+ <tr>
+ <th class="report-header" nowrap>Attempts</th>
+ <td width="100%">[% message_obj.attempts FILTER html %]</td>
+ </tr>
+ <tr>
+ <th class="report-header" nowrap>Last Attempt Time</th>
+ <td width="100%">[% message_obj.attempt_ts FILTER time FILTER html %]</td>
+ </tr>
+ <tr>
+ <th class="report-header" nowrap>Last Error</th>
+ <td width="100%"><b>[% message_obj.last_error FILTER html %]</b></td>
+ </tr>
+[% END %]
+
+<tr>
+ <td colspan="2">
+ [% IF json %]
+ <pre>[% json FILTER html %]</pre>
+ [% ELSE %]
+ <pre>[% message_obj.payload FILTER html %]</pre>
+ [% END %]
+ </td>
+</tr>
+
+<tr class="report-header">
+ <th colspan="2">
+ <a href="?id=push_queues.html">Return</a> |
+ <a onclick="return confirm('Are you sure you want to delete this message forever (a long time)?')"
+ href="?id=push_queues_view.html&amp;delete=1
+ [%- %]&amp;message=[% message_obj.id FILTER uri %]
+ [%- %]&amp;connector=[% message_obj.connector FILTER uri %]">Delete</a>
+ </th>
+</tr>
+
+</table>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/Push/template/en/default/setup/strings.txt.pl b/extensions/Push/template/en/default/setup/strings.txt.pl
new file mode 100644
index 000000000..bb135f5bb
--- /dev/null
+++ b/extensions/Push/template/en/default/setup/strings.txt.pl
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+%strings = (
+ feature_push_amqp => 'Push: AMQP Support',
+ feature_push_stomp => 'Push: STOMP Support',
+);
diff --git a/extensions/Push/web/admin.css b/extensions/Push/web/admin.css
new file mode 100644
index 000000000..c204fa62a
--- /dev/null
+++ b/extensions/Push/web/admin.css
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+.connector th {
+ text-align: left;
+ vertical-align: middle !important;
+}
+
+.option th {
+ text-align: right;
+ font-weight: normal !important;
+ vertical-align: middle !important;
+}
+
+.option .help {
+ font-style: italic;
+}
+
+.hidden {
+ display: none;
+}
+
+.required_option {
+ color: red;
+ cursor: help;
+}
+
+#report {
+ border: 1px solid #888888;
+ width: 100%;
+}
+
+#report td, #report th {
+ padding: 3px 10px 3px 3px;
+ border: 0px;
+}
+
+#report th {
+ text-align: left;
+}
+
+.report-header {
+ background: #cccccc;
+}
+
+.report-subheader {
+ background: #ffffff;
+}
+
+.report_row_odd {
+ background-color: #eeeeee;
+ color: #000000;
+}
+
+.report_row_even {
+ background-color: #ffffff;
+ color: #000000;
+}
+
+#report tr.row:hover {
+ background-color: #ccccff;
+}
+
+.rhs {
+ text-align: right !important;
+}
+
diff --git a/extensions/Push/web/admin.js b/extensions/Push/web/admin.js
new file mode 100644
index 000000000..599bfd742
--- /dev/null
+++ b/extensions/Push/web/admin.js
@@ -0,0 +1,37 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+var Dom = YAHOO.util.Dom;
+
+function toggle_options(visible, name) {
+ var rows = Dom.getElementsByClassName(name + '_tr');
+ for (var i = 0, l = rows.length; i < l; i++) {
+ if (visible) {
+ Dom.removeClass(rows[i], 'hidden');
+ } else {
+ Dom.addClass(rows[i], 'hidden');
+ }
+ }
+}
+
+function reset_to_defaults() {
+ if (!push_defaults) return;
+ for (var id in push_defaults) {
+ var el = Dom.get(id);
+ if (!el) continue;
+ if (el.nodeName == 'INPUT') {
+ el.value = push_defaults[id];
+ } else if (el.nodeName == 'SELECT') {
+ for (var i = 0, l = el.options.length; i < l; i++) {
+ if (el.options[i].value == push_defaults[id]) {
+ el.options[i].selected = true;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/extensions/REMO/Config.pm b/extensions/REMO/Config.pm
new file mode 100644
index 000000000..625e2afd9
--- /dev/null
+++ b/extensions/REMO/Config.pm
@@ -0,0 +1,34 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the REMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Byron Jones <glob@mozilla.com>
+# David Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::REMO;
+use strict;
+
+use constant NAME => 'REMO';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/REMO/Extension.pm b/extensions/REMO/Extension.pm
new file mode 100644
index 000000000..ed1792f99
--- /dev/null
+++ b/extensions/REMO/Extension.pm
@@ -0,0 +1,230 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the REMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Byron Jones <glob@mozilla.com>
+# David Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::REMO;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Constants;
+use Bugzilla::Util qw(trick_taint trim detaint_natural);
+use Bugzilla::Token;
+use Bugzilla::Error;
+
+our $VERSION = '0.01';
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ if ($page eq 'remo-form-payment.html') {
+ _remo_form_payment($vars);
+ }
+}
+
+sub _remo_form_payment {
+ my ($vars) = @_;
+ my $input = Bugzilla->input_params;
+
+ my $user = Bugzilla->login(LOGIN_REQUIRED);
+
+ if ($input->{'action'} eq 'commit') {
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+ my $dbh = Bugzilla->dbh;
+
+ my $bug_id = $input->{'bug_id'};
+ detaint_natural($bug_id);
+ my $bug = Bugzilla::Bug->check($bug_id);
+
+ # Detect if the user already used the same form to submit again
+ my $token = trim($input->{'token'});
+ if ($token) {
+ my ($creator_id, $date, $old_attach_id) = Bugzilla::Token::GetTokenData($token);
+ if (!$creator_id
+ || $creator_id != $user->id
+ || $old_attach_id !~ "^remo_form_payment:")
+ {
+ # The token is invalid.
+ ThrowUserError('token_does_not_exist');
+ }
+
+ $old_attach_id =~ s/^remo_form_payment://;
+ if ($old_attach_id) {
+ ThrowUserError('remo_payment_cancel_dupe',
+ { bugid => $bug_id, attachid => $old_attach_id });
+ }
+ }
+
+ # Make sure the user can attach to this bug
+ if (!$bug->user->{'canedit'}) {
+ ThrowUserError("remo_payment_bug_edit_denied",
+ { bug_id => $bug->id });
+ }
+
+ # Make sure the bug is under the correct product/component
+ if ($bug->product ne 'Mozilla Reps'
+ || $bug->component ne 'Budget Requests')
+ {
+ ThrowUserError('remo_payment_invalid_product');
+ }
+
+ my ($timestamp) = $dbh->selectrow_array("SELECT NOW()");
+
+ $dbh->bz_start_transaction;
+
+ # Create the comment to be added based on the form fields from rep-payment-form
+ my $comment;
+ $template->process("pages/comment-remo-form-payment.txt.tmpl", $vars, \$comment)
+ || ThrowTemplateError($template->error());
+ $bug->add_comment($comment, { isprivate => 0 });
+
+ # Attach expense report
+ # FIXME: Would be nice to be able to have the above prefilled comment and
+ # the following attachments all show up under a single comment. But the longdescs
+ # table can only handle one attach_id per comment currently. At least only one
+ # email is sent the way it is done below.
+ my $attachment;
+ if (defined $cgi->upload('expenseform')) {
+ # Determine content-type
+ my $content_type = $cgi->uploadInfo($cgi->param('expenseform'))->{'Content-Type'};
+
+ $attachment = Bugzilla::Attachment->create(
+ { bug => $bug,
+ creation_ts => $timestamp,
+ data => $cgi->upload('expenseform'),
+ description => 'Expense Form',
+ filename => scalar $cgi->upload('expenseform'),
+ ispatch => 0,
+ isprivate => 0,
+ mimetype => $content_type,
+ });
+
+ # Insert comment for attachment
+ $bug->add_comment('', { isprivate => 0,
+ type => CMT_ATTACHMENT_CREATED,
+ extra_data => $attachment->id });
+ }
+
+ # Attach receipts file
+ if (defined $cgi->upload("receipts")) {
+ # Determine content-type
+ my $content_type = $cgi->uploadInfo($cgi->param("receipts"))->{'Content-Type'};
+
+ $attachment = Bugzilla::Attachment->create(
+ { bug => $bug,
+ creation_ts => $timestamp,
+ data => $cgi->upload('receipts'),
+ description => "Receipts",
+ filename => scalar $cgi->upload("receipts"),
+ ispatch => 0,
+ isprivate => 0,
+ mimetype => $content_type,
+ });
+
+ # Insert comment for attachment
+ $bug->add_comment('', { isprivate => 0,
+ type => CMT_ATTACHMENT_CREATED,
+ extra_data => $attachment->id });
+ }
+
+ $bug->update($timestamp);
+
+ if ($token) {
+ trick_taint($token);
+ $dbh->do('UPDATE tokens SET eventdata = ? WHERE token = ?', undef,
+ ("remo_form_payment:" . $attachment->id, $token));
+ }
+
+ $dbh->bz_commit_transaction;
+
+ # Define the variables and functions that will be passed to the UI template.
+ $vars->{'attachment'} = $attachment;
+ $vars->{'bugs'} = [ new Bugzilla::Bug($bug_id) ];
+ $vars->{'header_done'} = 1;
+ $vars->{'contenttypemethod'} = 'autodetect';
+
+ my $recipients = { 'changer' => $user };
+ $vars->{'sent_bugmail'} = Bugzilla::BugMail::Send($bug_id, $recipients);
+
+ print $cgi->header();
+ # Generate and return the UI (HTML page) from the appropriate template.
+ $template->process("attachment/created.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+ else {
+ $vars->{'token'} = issue_session_token('remo_form_payment:');
+ }
+}
+
+sub post_bug_after_creation {
+ my ($self, $args) = @_;
+ my $vars = $args->{vars};
+ my $bug = $vars->{bug};
+ my $template = Bugzilla->template;
+
+ if (Bugzilla->input_params->{format}
+ && Bugzilla->input_params->{format} eq 'remo-swag')
+ {
+ # If the attachment cannot be successfully added to the bug,
+ # we notify the user, but we don't interrupt the bug creation process.
+ my $error_mode_cache = Bugzilla->error_mode;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+
+ my $attachment;
+ eval {
+ my $xml;
+ $template->process("bug/create/create-remo-swag.xml.tmpl", {}, \$xml)
+ || ThrowTemplateError($template->error());
+
+ $attachment = Bugzilla::Attachment->create(
+ { bug => $bug,
+ creation_ts => $bug->creation_ts,
+ data => $xml,
+ description => 'Remo Swag Request (XML)',
+ filename => 'remo-swag.xml',
+ ispatch => 0,
+ isprivate => 0,
+ mimetype => 'text/xml',
+ });
+ };
+ if ($@) {
+ warn "$@";
+ }
+
+ if ($attachment) {
+ # Insert comment for attachment
+ $bug->add_comment('', { isprivate => 0,
+ type => CMT_ATTACHMENT_CREATED,
+ extra_data => $attachment->id });
+ $bug->update($bug->creation_ts);
+ }
+ else {
+ $vars->{'message'} = 'attachment_creation_failed';
+ }
+
+ Bugzilla->error_mode($error_mode_cache);
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/REMO/template/en/default/bug/create/comment-mozreps.txt.tmpl b/extensions/REMO/template/en/default/bug/create/comment-mozreps.txt.tmpl
new file mode 100644
index 000000000..5e1275e0b
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/comment-mozreps.txt.tmpl
@@ -0,0 +1,95 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Byron Jones <glob@mozilla.com>
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+First Name:
+[%+ cgi.param('first_name') %]
+
+Last Name:
+[%+ cgi.param('last_name') %]
+
+Under 18 years old:
+[%+ IF cgi.param('underage') %]Yes[% ELSE %]No[% END %]
+
+Sex:
+[%+ cgi.param('sex') %]
+
+City:
+[%+ cgi.param('city') %]
+
+Country:
+[%+ cgi.param('country') %]
+
+Local Community:
+[% IF cgi.param('community') %]
+[%+ cgi.param('community') %]
+[% ELSE %]
+-
+[% END %]
+
+IM:
+[% IF cgi.param('im') %]
+[%+ cgi.param('im') %]
+[% ELSE %]
+-
+[% END %]
+
+Mozillians.org Account:
+[% IF cgi.param('mozillian') %]
+[%+ cgi.param('mozillian') %]
+[% ELSE %]
+-
+[% END %]
+
+References:
+[% IF cgi.param('references') %]
+[%+ cgi.param('references') %]
+[% ELSE %]
+-
+[% END %]
+
+Currently Involved with Mozilla:
+[% IF cgi.param('involved') %]
+[%+ cgi.param('involved') %]
+[% ELSE %]
+-
+[% END %]
+
+When First Contributed:
+[% IF cgi.param('firstcontribute') %]
+[%+ cgi.param('firstcontribute') %]
+[% ELSE %]
+-
+[% END %]
+
+Languages Spoken:
+[%+ cgi.param('languages') %]
+
+How did you lean about Mozilla Reps:
+[%+ cgi.param('learn') %]
+
+What motivates you most about joining Mozilla Reps:
+[%+ cgi.param('motivation') %]
+
+Comments:
+[% IF cgi.param('comments') %]
+[%+ cgi.param('comments') %]
+[% ELSE %]
+-
+[% END %]
diff --git a/extensions/REMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl b/extensions/REMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl
new file mode 100644
index 000000000..2ac4d9caa
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl
@@ -0,0 +1,55 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ #%]
+[%# INTERFACE:
+ # This template has no interface.
+ #
+ # Form variables from a bug submission (i.e. the fields on a template from
+ # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to
+ # pull out various custom fields and format an initial Description entry
+ # from them.
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Requester info:
+
+Requester: [% cgi.param('firstname') %] [%+ cgi.param('lastname') %]
+Profile page: [% cgi.param('profilepage') %]
+Event page: [% cgi.param('eventpage') %]
+Mentor Email: [% cgi.param('mentoremail') %]
+Paypal Account: [% cgi.param('paypal') %]
+Country You Reside: [% cgi.param('country') %]
+Advance payment needed: [% IF cgi.param('advancepayment') %]Yes[% ELSE %]No[% END %]
+
+Budget breakdown:
+
+Total amount requested in $USD: [% cgi.param('budgettotal') %]
+Costs per service:
+Service 1: [% cgi.param('service1') %] Cost: [% cgi.param('cost1') %]
+Service 2: [% cgi.param('service2') %] Cost: [% cgi.param('cost2') %]
+Service 3: [% cgi.param('service3') %] Cost: [% cgi.param('cost3') %]
+Service 4: [% cgi.param('service4') %] Cost: [% cgi.param('cost4') %]
+Service 5: [% cgi.param('service5') %] Cost: [% cgi.param('cost5') %]
+
+Additional costs: (add comment box)
+[% cgi.param('costadditional') %]
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/REMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl b/extensions/REMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl
new file mode 100644
index 000000000..dba982310
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl
@@ -0,0 +1,71 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ #%]
+[%# INTERFACE:
+ # This template has no interface.
+ #
+ # Form variables from a bug submission (i.e. the fields on a template from
+ # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to
+ # pull out various custom fields and format an initial Description entry
+ # from them.
+ #%]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Requester info:
+
+First name: [% cgi.param('firstname') %]
+Last name: [% cgi.param('lastname') %]
+Profile page: [% cgi.param('profilepage') %]
+Event name: [% cgi.param('eventname') %]
+Event page: [% cgi.param('eventpage') %]
+Estimated attendance: [% cgi.param('attendance') %]
+
+Shipping details:
+
+Ship swag before: [% cgi.param('cf_due_date') %]
+
+First name: [% cgi.param("shiptofirstname") %]
+Last name: [% cgi.param("shiptolastname") %]
+Address line 1: [% cgi.param("shiptoaddress1") %]
+Address line 2: [% cgi.param("shiptoaddress2") %]
+City: [% cgi.param("shiptocity") %]
+State/Region: [% cgi.param("shiptostate") %]
+Postal code: [% cgi.param("shiptopcode") %]
+Country: [% cgi.param("shiptocountry") %]
+Phone: [% cgi.param("shiptophone") %]
+[%+ IF cgi.param("shiptoidrut") %]Custom reference: [% cgi.param("shiptoidrut") %][% END %]
+
+Addition information for delivery person:
+[%+ cgi.param('shipadditional') %]
+
+Swag requested:
+
+Stickers: [% IF cgi.param('stickers') %]Yes[% ELSE %]No[% END %]
+Buttons: [% IF cgi.param('buttons') %]Yes[% ELSE %]No[% END %]
+Lanyards: [% IF cgi.param('lanyards') %]Yes[% ELSE %]No[% END %]
+T-shirts: [% IF cgi.param('tshirts') %]Yes[% ELSE %]No[% END %]
+Roll-up banners: [% IF cgi.param('rollupbanners') %]Yes[% ELSE %]No[% END %]
+Horizontal banner: [% IF cgi.param('horizontalbanner') %]Yes[% ELSE %]No[% END %]
+Booth cloth: [% IF cgi.param('boothcloth') %]Yes[% ELSE %]No[% END %]
+Pens: [% IF cgi.param('pens') %]Yes[% ELSE %]No[% END %]
+Other: [% IF cgi.param('otherswag') %][% cgi.param('otherswag') %][% ELSE %]No[% END %]
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/REMO/template/en/default/bug/create/create-mozreps.html.tmpl b/extensions/REMO/template/en/default/bug/create/create-mozreps.html.tmpl
new file mode 100644
index 000000000..bd918d803
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/create-mozreps.html.tmpl
@@ -0,0 +1,241 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Byron Jones <glob@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps - Application Form"
+ style_urls = [ "extensions/REMO/web/styles/moz_reps.css" ]
+%]
+
+[% USE Bugzilla %]
+[% mandatory = '<span class="mandatory" title="Required">*</span>' %]
+
+<script type="text/javascript">
+var Dom = YAHOO.util.Dom;
+
+function mandatory(ids) {
+ result = true;
+ for (i in ids) {
+ id = ids[i];
+ el = Dom.get(id);
+
+ if (el.type.toString() == "checkbox") {
+ value = el.checked;
+ } else {
+ value = el.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ el.value = value;
+ }
+
+ if (value == '') {
+ Dom.addClass(id, 'missing');
+ result = false;
+ } else {
+ Dom.removeClass(id, 'missing');
+ }
+ }
+ return result;
+}
+
+function underageWarning (el) {
+ if (el.checked) {
+ Dom.removeClass('underage_warning', 'bz_default_hidden');
+ Dom.get('submit').disabled = true;
+ }
+ else {
+ Dom.addClass('underage_warning', 'bz_default_hidden');
+ Dom.get('submit').disabled = false;
+ }
+}
+
+function submitForm() {
+ if (!mandatory([ 'first_name', 'last_name', 'sex', 'city', 'country',
+ 'languages', 'learn', 'motivation', 'privacy' ])
+ ) {
+ alert('Please enter all the required fields.');
+ return false;
+ }
+
+ Dom.get('short_desc').value =
+ "Application Form: " + Dom.get('first_name').value + ' ' + Dom.get('last_name').value;
+
+ return true;
+}
+
+</script>
+
+<noscript>
+<h1>Javascript is required to use this form.</h1>
+</noscript>
+
+<h1>Mozilla Reps - Application Form</h1>
+
+<form method="post" action="post_bug.cgi" id="tmRequestForm">
+<input type="hidden" name="product" value="Mozilla Reps">
+<input type="hidden" name="component" value="Mentorship">
+<input type="hidden" name="bug_severity" value="normal">
+<input type="hidden" name="rep_platform" value="All">
+<input type="hidden" name="priority" value="--">
+<input type="hidden" name="op_sys" value="Other">
+<input type="hidden" name="version" value="unspecified">
+<input type="hidden" name="groups" value="mozilla-reps">
+<input type="hidden" name="format" value="[% format FILTER html %]">
+<input type="hidden" name="created-format" value="[% format FILTER html %]">
+<input type="hidden" name="comment" id="comment" value="">
+<input type="hidden" name="short_desc" id="short_desc" value="">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="reps-form">
+
+<tr class="odd">
+ <th>First Name:[% mandatory FILTER none %]</th>
+ <td><input id="first_name" name="first_name" size="40" placeholder="John"></td>
+</tr>
+
+<tr class="even">
+ <th>Last Name:[% mandatory FILTER none %]</th>
+ <td><input id="last_name" name="last_name" size="40" placeholder="Doe"></td>
+</tr>
+
+<tr class="odd">
+ <th>Are you under 18 years old?:</th>
+ <td>
+ <input type="checkbox" id="underage" name="underage"
+ value="1" onclick="underageWarning(this);"><br>
+ </td>
+</tr>
+
+<tr id="underage_warning" class="odd bz_default_hidden">
+ <td colspan="2">
+ Mozilla Reps program is not currently accepting people under 18 years old.
+ Sorry for the inconvenience. In the meantime please check with your local Mozilla
+ group for other contribution opportunities
+ </td>
+</tr>
+
+<tr class="even">
+ <th>Sex:[% mandatory FILTER none %]</th>
+ <td>
+ <select id="sex" name="sex">
+ <option value="Male">Male</option>
+ <option value="Female">Female</option>
+ <option value="Other">Other</option>
+ </select>
+ </td>
+</tr>
+
+<tr class="odd">
+ <th>City:[% mandatory FILTER none %]</th>
+ <td><input id="city" name="city" size="40" placeholder="Your city"></td>
+</tr>
+
+<tr class="even">
+ <th>Country:[% mandatory FILTER none %]</th>
+ <td><input id="country" name="country" size="40" placeholder="Your country"></td>
+</tr>
+
+<tr class="odd">
+ <th>Local Community you participate in:</th>
+ <td><input id="community" name="community" size="40" placeholder="Name of your community"></td>
+</tr>
+
+<tr class="even">
+ <th>IM (specify service):</th>
+ <td><input id="im" name="im" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <th>Mozillians.org Account:</th>
+ <td><input id="mozillian" name="mozillian" size="40"></td>
+</tr>
+
+<tr class="even">
+ <th colspan="2">
+ References:
+ </th>
+</tr>
+<tr class="even">
+ <td colspan="2">
+ <textarea id="references" name="references" rows="4"
+ placeholder="Add contact info of people referencing you."></textarea>
+ </td>
+</tr>
+
+<tr class="odd">
+ <th colspan="2">
+ How are you involved with Mozilla?
+ </th>
+</tr>
+<tr class="odd">
+ <td colspan="2">
+ <textarea id="involved" name="involved" rows="4" placeholder="Add-ons, l10n, SUMO, QA, ..."></textarea>
+ </td>
+</tr>
+
+<tr class="even">
+ <th>
+ When did you first start contributing to Mozilla?
+ </th>
+ <td><input id="firstcontribute" name="firstcontribute" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <th>Languages Spoken:[% mandatory FILTER none %]</th>
+ <td><input id="languages" name="languages" size="40"></td>
+</tr>
+
+<tr class="even">
+ <th>How did you learn about Mozilla Reps?[% mandatory FILTER none %]</th>
+ <td><input id="learn" name="learn" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <th colspan="2">What motivates you most about joining Mozilla Reps?[% mandatory FILTER none %]</th>
+</tr>
+<tr class="odd">
+ <td colspan="2"><textarea id="motivation" name="motivation" rows="4"></textarea></td>
+</tr>
+
+<tr class="even">
+ <th colspan="2">Comments:</th>
+</tr>
+<tr class="even">
+ <td colspan="2"><textarea id="comments" name="comments" rows="4"></textarea></td>
+</tr>
+
+<tr class="odd">
+ <th>
+ I have read the
+ <a href="http://www.mozilla.com/en-US/privacy-policy" target="_blank">Mozilla Privacy Policy</a>:[% mandatory FILTER none %]
+ </th>
+ <td><input id="privacy" type="checkbox"></td>
+</tr>
+
+<tr class="even">
+ <td>&nbsp;</td>
+ <td align="right">
+ <input id="submit" type="submit" value="Submit" onclick="return submitForm()">
+ </td>
+</tr>
+
+</table>
+
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/template/en/default/bug/create/create-remo-budget.html.tmpl b/extensions/REMO/template/en/default/bug/create/create-remo-budget.html.tmpl
new file mode 100644
index 000000000..deabe8441
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/create-remo-budget.html.tmpl
@@ -0,0 +1,249 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps Budget Request Form"
+ style_urls = [ 'extensions/REMO/web/styles/moz_reps.css' ]
+ javascript_urls = [ 'extensions/REMO/web/js/form_validate.js',
+ 'js/util.js',
+ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+[% IF user.in_group("mozilla-reps") %]
+
+<p>These requests will only be visible to the person who submitted the request,
+any persons designated in the CC line, and authorized members of the Mozilla
+Rep team.</p>
+
+<script language="javascript" type="text/javascript">
+function trySubmit() {
+ var firstname = document.getElementById('firstname').value;
+ var lastname = document.getElementById('lastname').value;
+ var eventpage = document.getElementById('eventpage').value;
+ var shortdesc = 'Budget Request - ' + firstname + ' ' + lastname + ' - ' + eventpage;
+ document.getElementById('short_desc').value = shortdesc;
+ document.getElementById('cc').value = document.getElementById('mentoremail').value;
+ return true;
+}
+
+function validateAndSubmit() {
+ var alert_text = '';
+ if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n";
+ if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n";
+ if(!isFilledOut('profilepage')) alert_text += "Please enter a Mozilla Reps profile page.\n";
+ if(!isFilledOut('eventpage')) alert_text += "Please enter a event page address.\n";
+ if(!isFilledOut('mentoremail')) alert_text += "Please enter a valid [% terms.Bugzilla %] email for mentor.\n";
+ if(!isFilledOut('country')) alert_text += "Please enter a valid value for country.\n";
+ if(!isFilledOut('budgettotal')) alert_text += "Please enter the total budget for the event.\n";
+ if(!isFilledOut('service1') || !isFilledOut('cost1')) alert_text += "Please enter at least one service and cost value.\n";
+
+ //Everything required is filled out..try to submit the form!
+ if(alert_text == '') {
+ return trySubmit();
+ }
+
+ //alert text, stay here on the pagee
+ alert(alert_text);
+ return false;
+}
+</script>
+
+<h1>Mozilla Reps - Budget Request Form</h1>
+
+<p>
+ If your request is Community IT related please file it
+ <a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Mozilla%20Reps;component=Community%20IT%20Requests">here</a>.
+</p>
+
+<p>
+ <span class="required_star">*</span> - <span class="required_explanation">Required Fields</span>
+</p>
+
+<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+
+ <input type="hidden" name="format" value="remo-budget">
+ <input type="hidden" name="created-format" value="remo-budget">
+ <input type="hidden" name="product" value="Mozilla Reps">
+ <input type="hidden" name="component" value="Budget Requests">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="cc" id="cc" value="">
+ <input type="hidden" name="groups" value="mozilla-reps">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="reps-form">
+
+<tr class="odd">
+ <th class="field_label required">First Name:</th>
+ <td>
+ <input type="text" name="firstname" id="firstname" value="" size="40" placeholder="John">
+ </td>
+</tr>
+
+<tr class="even">
+ <th class="field_label required">Last Name:</th>
+ <td>
+ <input type="text" name="lastname" id="lastname" value="" size="40" placeholder="Doe">
+ </td>
+</tr>
+
+<tr class="odd">
+ <th class="field_label required">Mozilla Reps Profile Page:</th>
+ <td>
+ <input type="text" name="profilepage" id="profilepage"
+ value="" size="40" placeholder="https://reps.mozilla.org/u/JohnDoe">
+ </td>
+</tr>
+
+<tr class="even">
+ <th class="field_label required">Event Page:</th>
+ <td>
+ <input type="text" name="eventpage" id="eventpage"
+ value="" size="40" placeholder="https://reps.mozilla.org/e/TestEvent">
+ </td>
+</tr>
+
+<tr class="odd">
+ <th class="field_label required">[% terms.Bugzilla %] Email of Your Mentor:</th>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "mentoremail"
+ name => "mentoremail"
+ value => ""
+ size => 40
+ %]
+ </td>
+</tr>
+
+<tr class="even">
+ <th class="field_label">Paypal Account Email:</th>
+ <td>
+ <input type="text" name="paypal" id="paypal"
+ value="" size="40" placeholder=""><br>
+ <span style="font-size: smaller;">
+ * Currently, you CANNOT make payments using other online payment services.</span>
+ </td>
+</tr>
+
+<tr class="odd">
+ <th class="field_label required">Country You Reside:</th>
+ <td>
+ <input type="text" name="country" id="country"
+ value="" size="40" placeholder="USA">
+ </td>
+</tr>
+
+<tr class="even">
+ <th class="field_label">Is advance payment needed?</th>
+ <td>
+ <input type="checkbox" name="advancepayment" id="advancepayment" value="1">
+ </td>
+</tr>
+
+<tr class="odd">
+ <td><!--spacer-->&nbsp;</td>
+ <td><!--spacer-->&nbsp;</td>
+</tr>
+
+<tr class="even">
+ <th colspan="2" class="field_label">Budget Request:</th>
+</tr>
+
+<tr class="even">
+ <th class="field_label required">Total amount requested in $USD:</th>
+ <td>
+ <input type="text" name="budgettotal" id="budgettotal" value="" size="40">
+ </td>
+ </tr>
+
+<tr class="even">
+ <th colspan="2" class="field_label">Costs per service:</th>
+</tr>
+
+<tr class="even">
+ <td colspan="2">
+ <table>
+ <tr>
+ <th class="field_label required">Service 1:</th>
+ <td><input type="text" id="service1" name="service1" size="30"></td>
+ <th class="field_label required">Cost 1:</th>
+ <td><input type="text" id="cost1" name="cost1" size="30"></td>
+ </tr>
+ <tr>
+ <th class="field_lable">Service 2:</th>
+ <td><input type="text" id="service2" name="service2" size="30"></td>
+ <th class="field_lable">Cost 2:</th>
+ <td><input type="text" id="cost2" name="cost2" size="30"></td>
+ </tr>
+ <tr>
+ <th class="field_lable">Service 3:</th>
+ <td><input type="text" id="service3" name="service3" size="30"></td>
+ <th class="field_lable">Cost 3:</th>
+ <td><input type="text" id="cost3" name="cost3" size="30"></td>
+ </tr>
+ <tr>
+ <th class="field_lable">Service 4:</th>
+ <td><input type="text" id="service4" name="service4" size="30"></td>
+ <th class="field_lable">Cost 4:</th>
+ <td><input type="text" id="cost4" name="cost4" size="30"></td>
+ </tr>
+ <tr>
+ <th class="field_lable">Service 5:</th>
+ <td><input type="text" id="service5" name="service5" size="30"></td>
+ <th class="field_lable">Cost 5:</th>
+ <td><input type="text" id="cost5" name="cost5" size="30"></td>
+ </tr>
+ </table>
+ </td>
+</tr>
+
+<tr class="even">
+ <th colspan="2" class="field_label">Additional costs:</th>
+</tr>
+
+<tr class="even">
+ <td colspan="2">
+ <textarea id="costadditional" name="costadditional" rows="5" cols="50"></textarea>
+ </td>
+</tr>
+
+<tr class="odd">
+ <td>&nbsp;</td>
+ <td align="right">
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+
+</table>
+
+</form>
+
+<p style="font-weight:bold;">
+ Budget requests received less than 3 weeks before the targeted launch date of the
+ event/activity in question will automatically be rejected (exceptions can be made
+ but only with council approval). This 3-week “buffer” guarantees that each budget
+ request undergoes the same thorough selection process.
+</p>
+
+<p>
+ Thanks for contacting us.
+</p>
+
+[% ELSE %]
+ <p>Sorry, you do not have access to this page.</p>
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/template/en/default/bug/create/create-remo-swag.html.tmpl b/extensions/REMO/template/en/default/bug/create/create-remo-swag.html.tmpl
new file mode 100644
index 000000000..e618be726
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/create-remo-swag.html.tmpl
@@ -0,0 +1,293 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps Swag Request Form"
+ javascript_urls = [ 'extensions/REMO/web/js/swag.js',
+ 'extensions/REMO/web/js/form_validate.js',
+ 'js/field.js',
+ 'js/util.js' ]
+ style_urls = [ "extensions/REMO/web/styles/moz_reps.css" ]
+ yui = [ 'calendar' ]
+%]
+
+[% IF !user.in_group("mozilla-reps") %]
+ <p>Sorry, you do not have access to this page.</p>
+ [% RETURN %]
+[% END %]
+
+
+<p>These requests will only be visible to the person who submitted the request,
+any persons designated in the CC line, and authorized members of the Mozilla Rep team.</p>
+
+<script language="javascript" type="text/javascript">
+function trySubmit() {
+ var eventname = document.getElementById('eventname').value;
+ var shortdesc = 'Swag Request - ' + eventname;
+ document.getElementById('short_desc').value = shortdesc;
+ return true;
+}
+
+function validateAndSubmit() {
+ var alert_text = '';
+ if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n";
+ if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n";
+ if(!isFilledOut('profilepage')) alert_text += "Please enter your Mozilla Reps profile page\n";
+ if(!isFilledOut('eventname')) alert_text += "Please enter your event name\n";
+ if(!isFilledOut('eventpage')) alert_text += "Please enter the event page.\n";
+ if(!isFilledOut('attendance')) alert_text += "Please enter the estimated attendance.\n";
+ if(!isFilledOut('shiptofirstname')) alert_text += "Please enter the shipping first name\n";
+ if(!isFilledOut('shiptolastname')) alert_text += "Please enter the shipping last name\n";
+ if(!isFilledOut('shiptoaddress1')) alert_text += "Please enter the ship to address\n";
+ if(!isFilledOut('shiptocity')) alert_text += "Please enter the ship to city\n";
+ if(!isFilledOut('shiptocountry')) alert_text += "Please enter the ship to country\n";
+ if(!isFilledOut('shiptopcode')) alert_text += "Please enter the ship to postal code\n";
+ if(!isFilledOut('shiptophone')) alert_text += "Please enter the ship to contact number\n";
+
+ //Everything required is filled out..try to submit the form!
+ if(alert_text == '') {
+ return trySubmit();
+ }
+
+ //alert text, stay here on the pagee
+ alert(alert_text);
+ return false;
+}
+
+</script>
+
+<h1>Mozilla Reps - Swag Request Form</h1>
+
+<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+
+ <input type="hidden" name="format" value="remo-swag">
+ <input type="hidden" name="product" value="Mozilla Reps">
+ <input type="hidden" name="component" value="Swag Requests">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-reps">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table id="reps-form">
+
+<tr class="odd">
+ <td><strong>First Name: <span style="color: red;" title="Required">*</span></strong></td>
+ <td>
+ <input type="text" name="firstname" id="firstname" placeholder="John" size="40">
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>Last Name: <span style="color: red;" title="Required">*</span></strong></td>
+ <td>
+ <input type="text" name="lastname" id="lastname" placeholder="Doe" size="40">
+ </td>
+</tr>
+
+<tr class="odd">
+ <td>
+ <strong>Mozilla Reps Profile Page:
+ <span style="color: red;" title="Required">*</span></strong>
+ </td>
+ <td>
+ <input type="text" name="profilepage" id="profilepage" size="40">
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>Event Name: <span style="color: red;" title="Required">*</span></strong></td>
+ <td>
+ <input type="text" name="eventname" id="eventname" size="40">
+ </td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Event Page: <span style="color: red;" title="Required">*</span></strong></td>
+ <td>
+ <input type="text" name="eventpage" id="eventpage" size="40">
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>Estimated Attendance: <span style="color: red;" title="Required">*</span></strong></td>
+ <td>
+ <select id="attendance" name="attendance">
+ <option value="1-50">1-50</option>
+ <option value="51-200">51-200</option>
+ <option value="201-500">201-500</option>
+ <option value="501-1000+">501-1000+</option>
+ </select>
+ </td>
+</tr
+
+<tr class="odd">
+ <td><!--spacer-->&nbsp;</td>
+ <td><!--spacer-->&nbsp;</td>
+</tr>
+
+<tr class="even">
+ <td colspan="2"><strong>Shipping Details:</strong></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Ship Before:</strong>
+ <td>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default,
+ field = bug_fields.cf_due_date
+ value = default.cf_due_date,
+ editable = 1,
+ no_tds = 1
+ %]
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>First Name: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptofirstname" id="shiptofirstname" placeholder="John" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Last Name: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptolastname" id="shiptolastname" placeholder="Doe" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Address Line 1: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptoaddress1" id="shiptoaddress1" placeholder="123 Main St." size="40"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Address Line 2:</strong></td>
+ <td><input name="shiptoaddress2" id="shiptoaddress2" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>City: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptocity" id="shiptocity" size="40" placeholder="Anytown"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>State/Region (if applicable):</strong></td>
+ <td><input name="shiptostate" id="shiptostate" placeholder="CA" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Country: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptocountry" id="shiptocountry" placeholder="USA" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Postal Code: <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptopcode" id="shiptopcode" placeholder="90210" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Phone (including country code): <span style="color: red;" title="Required">*</span></strong></td>
+ <td><input name="shiptophone" id="shiptophone" placeholder="919-555-1212" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Custom Reference<br>
+ (Fiscal or VAT-number, if known):</strong><br><small>(if your country requires this)</small>
+ </td>
+ <td><input name="shiptoidrut" id="shiptoidrut" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td colspan="2">
+ <strong>Addition information for delivery person:</strong><br>
+ <textarea id="shipadditional" name="shipadditional" rows="4"></textarea>
+ </td>
+</tr>
+
+<tr class="odd">
+ <td><!--spacer-->&nbsp;</td>
+ <td><!--spacer-->&nbsp;</td>
+</tr>
+
+<tr class="even">
+ <td colspan="2"><strong>Swag Requested:</strong></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Stickers:</strong></td>
+ <td><input type="checkbox" id="stickers" name="stickers" value="1"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Buttons:</strong></td>
+ <td><input type="checkbox" id="buttons" name="buttons" value="1"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Lanyards:</strong></td>
+ <td><input type="checkbox" id="lanyards" name="lanyards" value="1"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>T-Shirts:</strong></td>
+ <td><input type="checkbox" id="tshirts" name="tshirts" value="1"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Roll-Up Banners:</strong></td>
+ <td><input type="checkbox" id="rollupbanners" name="rollupbanners" value="1"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Horizontal Banner:</strong></td>
+ <td><input type="checkbox" id="horizontalbanner" name="horizontalbanner" value="1"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Booth Cloth:</strong></td>
+ <td><input type="checkbox" id="boothcloth" name="boothcloth" value="1"></td>
+</tr>
+
+<tr class="even">
+ <td><strong>Pens:</strong></td>
+ <td><input type="checkbox" id="pens" name="pens" value="1"></td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Other:</strong> (please specify)</td>
+ <td><input type="text" id="otherswag" name="otherswag" size="40"></td>
+</tr>
+
+<tr class="even">
+ <td>&nbsp;</td>
+ <td align="right">
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+
+</table>
+
+<p>
+ Quantities of different swag items requested that will actually be shipped
+ depend on stock availability and number of attendees. Mozilla cannot guarantee
+ that all items requested will be in stock at the time of shipment and you will
+ be notified in case an item cannot be shipped. Please request swag at least 1
+ month before desired delivery date.
+</p>
+
+<p>
+ <strong><span style="color: red;">*</span></strong> - Required field<br />
+ Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/template/en/default/bug/create/create-remo-swag.xml.tmpl b/extensions/REMO/template/en/default/bug/create/create-remo-swag.xml.tmpl
new file mode 100644
index 000000000..4308bc5ac
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/create-remo-swag.xml.tmpl
@@ -0,0 +1,104 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+<?xml version="1.0" [% IF Param('utf8') %]encoding="UTF-8" [% END %]standalone="yes" ?>
+<!DOCTYPE remoswag [
+<!ELEMENT remoswag (firstname,
+ lastname,
+ wikiprofile,
+ eventname,
+ wikipage,
+ attendance,
+ shipping,
+ swagrequested)>
+<!ELEMENT firstname (#PCDATA)>
+<!ELEMENT lastname (#PCDATA)>
+<!ELEMENT wikiprofile (#PCDATA)>
+<!ELEMENT eventname (#PCDATA)>
+<!ELEMENT wikipage (#PCDATA)>
+<!ELEMENT attendance (#PCDATA)>
+<!ELEMENT shipping (shipbeforedate,
+ shiptofirstname,
+ shiptolastname,
+ shiptoaddress1,
+ shiptoaddress2,
+ shiptocity,
+ shiptostate,
+ shiptopcode,
+ shiptocountry,
+ shiptophone,
+ shiptoidrut,
+ shipadditional)>
+<!ELEMENT shipbeforedate (#PCDATA)>
+<!ELEMENT shiptofirstname (#PCDATA)>
+<!ELEMENT shiptolastname (#PCDATA)>
+<!ELEMENT shiptoaddress1 (#PCDATA)>
+<!ELEMENT shiptoaddress2 (#PCDATA)>
+<!ELEMENT shiptocity (#PCDATA)>
+<!ELEMENT shiptostate (#PCDATA)>
+<!ELEMENT shiptopcode (#PCDATA)>
+<!ELEMENT shiptocountry (#PCDATA)>
+<!ELEMENT shiptophone (#PCDATA)>
+<!ELEMENT shiptoidrut (#PCDATA)>
+<!ELEMENT shipadditional (#PCDATA)>
+<!ELEMENT swagrequested (stickers,
+ buttons,
+ posters,
+ lanyards,
+ tshirts,
+ rollupbanners,
+ horizontalbanner,
+ boothcloth,
+ pens,
+ otherswag)>
+<!ELEMENT stickers (#PCDATA)>
+<!ELEMENT buttons (#PCDATA)>
+<!ELEMENT posters (#PCDATA)>
+<!ELEMENT lanyards (#PCDATA)>
+<!ELEMENT tshirts (#PCDATA)>
+<!ELEMENT rollupbanners (#PCDATA)>
+<!ELEMENT horizontalbanners (#PCDATA)>
+<!ELEMENT boothcloth (#PCDATA)>
+<!ELEMENT pens (#PCDATA)>
+<!ELEMENT otherswag (#PCDATA)>]>
+<remoswag>
+ <firstname>[% cgi.param('firstname') FILTER xml %]</firstname>
+ <lastname>[% cgi.param('lastname') FILTER xml %]</lastname>
+ <wikiprofile>[% cgi.param('wikiprofile') FILTER xml %]</wikiprofile>
+ <eventname>[% cgi.param('eventname') FILTER xml %]</eventname>
+ <wikipage>[% cgi.param('wikipage') FILTER xml %]</wikipage>
+ <attendance> [% cgi.param('attendance') FILTER xml %]</attendance>
+ <shipping>
+ <shipbeforedate>[% cgi.param('cf_due_date') FILTER xml %]</shipbeforedate>
+ <shiptofirstname>[% cgi.param("shiptofirstname") FILTER xml %]</shiptofirstname>
+ <shiptolastname>[% cgi.param("shiptolastname") FILTER xml %]</shiptolastname>
+ <shiptoaddress1>[% cgi.param("shiptoaddress1") FILTER xml %]</shiptoaddress1>
+ <shiptoaddress2>[% cgi.param("shiptoaddress2") FILTER xml %]</shiptoaddress2>
+ <shiptocity>[% cgi.param("shiptocity") FILTER xml %]</shiptocity>
+ <shiptostate>[% cgi.param("shiptostate") FILTER xml %]</shiptostate>
+ <shiptopcode>[% cgi.param("shiptopcode") FILTER xml %]</shiptopcode>
+ <shiptocountry>[% cgi.param("shiptocountry") FILTER xml %]</shiptocountry>
+ <shiptophone>[% cgi.param("shiptophone") FILTER xml %]</shiptophone>
+ <shiptoidrut>[% cgi.param("shiptoidrut") FILTER xml %]</shiptoidrut>
+ <shipadditional>[% cgi.param('shipadditional') || '' FILTER xml %]</shipadditional>
+ </shipping>
+ <swagrequested>
+ <stickers>[% (cgi.param('stickers') ? 1 : 0) FILTER xml %]</stickers>
+ <buttons>[% (cgi.param('buttons') ? 1 : 0) FILTER xml %]</buttons>
+ <posters>[% (cgi.param('posters') ? 1 : 0) FILTER xml %]</posters>
+ <lanyards>[% (cgi.param('lanyards') ? 1 : 0) FILTER xml %]</lanyards>
+ <tshirts>[% (cgi.param('tshirts') ? 1 : 0) FILTER xml %]</tshirts>
+ <rollupbanners>[% (cgi.param('rollupbanners') ? 1 : 0) FILTER xml %]</rollupbanners>
+ <horizontalbanner>[% (cgi.param('horizontalbanner') ? 1 : 0) FILTER xml %]</horizontalbanner>
+ <boothcloth>[% (cgi.param('boothcloth') ? 1 : 0) FILTER xml %]</boothcloth>
+ <pens>[% (cgi.param('pens') ? 1 : 0) FILTER xml %]</pens>
+ <otherswag>[% cgi.param('otherswag') || '' FILTER xml %]</otherswag>
+ </swagrequested>
+</remoswag>
diff --git a/extensions/REMO/template/en/default/bug/create/created-mozreps.html.tmpl b/extensions/REMO/template/en/default/bug/create/created-mozreps.html.tmpl
new file mode 100644
index 000000000..a8a3ca112
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/created-mozreps.html.tmpl
@@ -0,0 +1,38 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Byron Jones <glob@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps - Application Form"
+
+%]
+
+<h1>Thank you!</h1>
+
+<p>
+Thank you for submitting your Mozilla Reps Application Form. A Mozilla Rep
+mentor will contact you shortly at your bugzilla email address.
+</p>
+
+<p style="font-size: x-small">
+Reference: <a href="show_bug.cgi?id=[% id FILTER uri %]">#[% id FILTER html %]</a>
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/template/en/default/bug/create/created-remo-budget.html.tmpl b/extensions/REMO/template/en/default/bug/create/created-remo-budget.html.tmpl
new file mode 100644
index 000000000..62430bf9c
--- /dev/null
+++ b/extensions/REMO/template/en/default/bug/create/created-remo-budget.html.tmpl
@@ -0,0 +1,27 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps Budget Request Form"
+%]
+
+<h1>Thank you!</h1>
+
+<p>
+ Your budget request has been successfully submitted. Please make sure to
+ follow-up with your mentor so (s)he can verify your request. CC him/her
+ on the [% terms.bug %] if needed.
+</p>
+
+<p style="font-size: x-small">
+ Reference: <a href="show_bug.cgi?id=[% id FILTER uri %]">#[% id FILTER html %]</a>
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/REMO/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..200e678be
--- /dev/null
+++ b/extensions/REMO/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,40 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <bjones@mozilla.com>
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% IF error == "remo_payment_invalid_product" %]
+ [% title = "Mozilla Reps Payment Invalid Bug" %]
+ You can only attach budget payment information to [% terms.bugs %] under
+ the product 'Mozilla Reps' and component 'Budget Requests'.
+
+[% ELSIF error == "remo_payment_bug_edit_denied" %]
+ [% title = "Mozilla Reps Payment Bug Edit Denied" %]
+ You do not have permission to edit [% terms.bug %] '[% bug_id FILTER html %]'.
+
+[% ELSIF error == "remo_payment_cancel_dupe" %]
+ [% title = "Already filed payment request" %]
+ You already used the form to file
+ <a href="[% urlbase FILTER html %]attachment.cgi?id=[% attachid FILTER uri %]&action=edit">
+ attachment [% attachid FILTER uri %]</a>.<br>
+ <br>
+ You can either <a href="[% urlbase FILTER html %]page.cgi?id=remo-form-payment.html">
+ create a new payment request</a> or [% "go back to $terms.bug $bugid" FILTER bug_link(bugid) FILTER none %].
+
+[% END %]
diff --git a/extensions/REMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl b/extensions/REMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl
new file mode 100644
index 000000000..95c0af6e8
--- /dev/null
+++ b/extensions/REMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl
@@ -0,0 +1,37 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+
+Mozilla Reps Payment Request
+----------------------------
+
+Requester info:
+
+First name: [% cgi.param('firstname') %]
+Last name: [% cgi.param('lastname') %]
+Wiki user profile: [% cgi.param('wikiprofile') %]
+Event wiki page: [% cgi.param('wikipage') %]
+Budget request [% terms.bug %]: [% cgi.param('bug_id') %]
+Have you already received payment for this event? [% IF cgi.param('receivedpayment') %]Yes[% ELSE %]No[% END %]
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/REMO/template/en/default/pages/remo-form-payment.html.tmpl b/extensions/REMO/template/en/default/pages/remo-form-payment.html.tmpl
new file mode 100644
index 000000000..0f5f206d3
--- /dev/null
+++ b/extensions/REMO/template/en/default/pages/remo-form-payment.html.tmpl
@@ -0,0 +1,243 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the REMO Extension
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps Payment Form"
+ style_urls = [ 'extensions/REMO/web/styles/moz_reps.css' ]
+ javascript_urls = [ 'extensions/REMO/web/js/form_validate.js',
+ 'js/util.js',
+ 'js/field.js' ]
+ yui = ['connection', 'json']
+%]
+
+<script language="javascript" type="text/javascript">
+
+var bug_cache = {};
+
+function validateAndSubmit() {
+ var alert_text = '';
+ if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n";
+ if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n";
+ if(!isFilledOut('wikiprofile')) alert_text += "Please enter a wiki user profile.\n";
+ if(!isFilledOut('wikipage')) alert_text += "Please enter a wiki page address.\n";
+ if(!isFilledOut('bug_id')) alert_text += "Please enter a valid [% terms.bug %] id to attach this additional information to.\n";
+ if(!isFilledOut('expenseform')) alert_text += "Please enter an expense form to upload.\n";
+ if(!isFilledOut('receipts')) alert_text += "Please enter a receipts file to upload.\n";
+
+ if (alert_text) {
+ alert(alert_text);
+ return false;
+ }
+
+ return true;
+}
+
+function togglePaymentInfo (e) {
+ var div = document.getElementById('paymentinfo');
+ if (e.checked == false) {
+ div.style.display = 'block';
+ }
+ else {
+ div.style.display = 'none';
+ }
+}
+
+function getBugInfo (e, div) {
+ var bug_id = e.value;
+ div = document.getElementById(div);
+
+ if (!bug_id) {
+ div.innerHTML = "";
+ return true;
+ }
+
+ div.style.display = 'block';
+
+ if (bug_cache[bug_id]) {
+ div.innerHTML = bug_cache[bug_id];
+ e.disabled = false;
+ return true;
+ }
+
+ e.disabled = true;
+ div.innerHTML = 'Getting [% terms.bug %] info...';
+
+ YAHOO.util.Connect.setDefaultPostHeader('application/json', true);
+ YAHOO.util.Connect.asyncRequest(
+ 'POST',
+ 'jsonrpc.cgi',
+ {
+ success: function(res) {
+ var bug_message = "";
+ data = YAHOO.lang.JSON.parse(res.responseText);
+ if (data.error) {
+ bug_message = "Get [% terms.bug %] failed: " + data.error.message;
+ }
+ else if (data.result) {
+ if (data.result.bugs[0].product !== 'Mozilla Reps'
+ || data.result.bugs[0].component !== 'Budget Requests')
+ {
+ bug_message = "You can only attach budget payment " +
+ "information to [% terms.bugs %] under the product " +
+ "'Mozilla Reps' and component 'Budget Requests'.";
+ }
+ else {
+ bug_message = "[% terms.Bug %] " + bug_id + " - " + data.result.bugs[0].status +
+ " - " + data.result.bugs[0].summary;
+ }
+ }
+ else {
+ bug_message = "Get [% terms.bug %] failed: " + res.responseText;
+ }
+ div.innerHTML = bug_message;
+ bug_cache[bug_id] = bug_message;
+ e.disabled = false;
+ },
+ failure: function(res) {
+ if (res.responseText) {
+ div.innerHTML = "Get [% terms.bug %] failed: " + res.responseText;
+ }
+ }
+ },
+ YAHOO.lang.JSON.stringify({
+ version: "1.1",
+ method: "Bug.get",
+ id: bug_id,
+ params: {
+ ids: [ bug_id ],
+ include_fields: [ 'product', 'component', 'status', 'summary' ]
+ }
+ })
+ );
+}
+
+</script>
+
+<h1>Mozilla Reps - Payment Form</h1>
+
+<form method="post" action="page.cgi" id="paymentForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+<input type="hidden" id="id" name="id" value="remo-form-payment.html">
+<input type="hidden" id="token" name="token" value="[% token FILTER html %]">
+<input type="hidden" id="action" name="action" value="commit">
+
+<table id="reps-form">
+
+<tr class="odd">
+ <td width="25%"><strong>First Name: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="firstname" id="firstname" value="" size="40" placeholder="John">
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>Last Name: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="lastname" id="lastname" value="" size="40" placeholder="Doe">
+ </td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Wiki user profile:<span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="wikiprofile" id="wikiprofile" value="" size="40" placeholder="JohnDoe">
+ </td>
+</tr>
+
+<tr class="even">
+ <td><strong>Event wiki page: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="wikipage" id="wikipage" value="" size="40">
+ </td>
+</tr>
+
+<tr class="odd">
+ <td><strong>Budget request [% terms.bug %]: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="bug_id" id="bug_id" value="" size="40"
+ onblur="getBugInfo(this,'bug_info');")>
+ </td>
+</tr>
+
+<tr class="odd">
+ <td colspan="2">
+ <div id="bug_info" style="display:none;"></div>
+ </td>
+</tr>
+
+<tr class="even">
+ <td colspan="2">
+ <strong>Have you already received payment for this event?</strong>
+ <input type="checkbox" name="receivedpayment" id="receivedpayment" value="1"
+ onchange="togglePaymentInfo(this);" checked="true">
+ <div id="paymentinfo" style="display:none;">
+ Please send an email to William at mozilla.com with all the information below:<br>
+ <br>
+ Payment information:<br>
+ Bank name:<br>
+ Bank address: <br>
+ IBAN:<br>
+ Swift code/BIC:<br>
+ Additional bank details (if necessary):
+ </div>
+ </td>
+</tr>
+
+<tr class="odd">
+ <td colspan="2">
+ <strong>Expense form and scanned receipts/invoices:</strong>
+ </td>
+</tr>
+
+<tr class="odd">
+ <td>Expense Form: <span style="color: red;">*</span></td>
+ <td><input type="file" id="expenseform" name="expenseform" size="40"></td>
+</tr>
+
+<tr class="odd">
+ <td valign="top">Receipts File: <span style="color: red;">*</span></td>
+ <td>
+ <input type="file" id="receipts" name="receipts" size="40"><br>
+ <font style="color:red;">
+ Please black out any bank account information included<br>
+ on receipts before attaching them.
+ </font>
+ </td>
+</tr>
+
+<tr class="even">
+ <td>&nbsp;</td>
+ <td align="right">
+ <input type="submit" id="commit" value="Submit Request">
+ </td>
+</tr>
+
+</table>
+
+</form>
+
+<p>
+ <strong><span style="color: red;">*</span></strong> - Required field<br>
+ Thanks for contacting us.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/REMO/web/js/form_validate.js b/extensions/REMO/web/js/form_validate.js
new file mode 100644
index 000000000..6c8fa6f07
--- /dev/null
+++ b/extensions/REMO/web/js/form_validate.js
@@ -0,0 +1,21 @@
+/**
+ * Some Form Validation and Interaction
+ **/
+//Makes sure that there is an '@' in the address with a '.'
+//somewhere after it (and at least one character in between them
+
+function isValidEmail(email) {
+ var at_index = email.indexOf("@");
+ var last_dot = email.lastIndexOf(".");
+ return at_index > 0 && last_dot > (at_index + 1);
+}
+
+//Takes a DOM element id and makes sure that it is filled out
+function isFilledOut(elem_id) {
+ var str = document.getElementById(elem_id).value;
+ return str.length>0 && str!="noneselected";
+}
+
+function isChecked(elem_id) {
+ return document.getElementById(elem_id).checked;
+}
diff --git a/extensions/REMO/web/js/swag.js b/extensions/REMO/web/js/swag.js
new file mode 100644
index 000000000..3b69bbab8
--- /dev/null
+++ b/extensions/REMO/web/js/swag.js
@@ -0,0 +1,60 @@
+/**
+ * Swag Request Form Functions
+ * Form Interal Swag Request Form
+ * dtran
+ * 7/6/09
+ **/
+
+
+function evalToNumber(numberString) {
+ if(numberString=='') return 0;
+ return parseInt(numberString);
+}
+
+function evalToNumberString(numberString) {
+ if(numberString=='') return '0';
+ return numberString;
+}
+//item_array should be an array of DOM element ids
+function getTotal(item_array) {
+ var total = 0;
+ for(var i in item_array) {
+ total += evalToNumber(document.getElementById(item_array[i]).value);
+ }
+ return total;
+}
+
+function calculateTotalSwag() {
+ document.getElementById('Totalswag').value =
+ getTotal( new Array('Lanyards',
+ 'Stickers',
+ 'Bracelets',
+ 'Tattoos',
+ 'Buttons',
+ 'Posters'));
+
+}
+
+
+function calculateTotalMensShirts() {
+ document.getElementById('mens_total').value =
+ getTotal( new Array('mens_s',
+ 'mens_m',
+ 'mens_l',
+ 'mens_xl',
+ 'mens_xxl',
+ 'mens_xxxl'));
+
+}
+
+
+function calculateTotalWomensShirts() {
+ document.getElementById('womens_total').value =
+ getTotal( new Array('womens_s',
+ 'womens_m',
+ 'womens_l',
+ 'womens_xl',
+ 'womens_xxl',
+ 'womens_xxxl'));
+
+}
diff --git a/extensions/REMO/web/styles/moz_reps.css b/extensions/REMO/web/styles/moz_reps.css
new file mode 100644
index 000000000..989733c41
--- /dev/null
+++ b/extensions/REMO/web/styles/moz_reps.css
@@ -0,0 +1,44 @@
+#reps-form {
+ width: 700px;
+ border-spacing: 0px;
+ border: 4px solid #e0e0e0;
+}
+
+#reps-form th, #reps-form td {
+ padding: 5px;
+}
+
+#reps-form .even th, #reps-form .even td {
+ background: #e0e0e0;
+}
+
+#reps-form th {
+ text-align: left;
+}
+
+#reps-form textarea {
+ font-family: Verdana, sans-serif;
+ font-size: small;
+ width: 590px;
+}
+
+#reps-form .mandatory {
+ color: red;
+ font-size: 80%;
+}
+
+#reps-form .missing {
+ box-shadow: #FF0000 0 0 1.5px 1px;
+}
+
+#reps-form .hidden {
+ display: none;
+}
+
+#reps-form .subTH {
+ padding-left: 2em;
+}
+
+#reps-form .missing {
+ background: #FFC1C1;
+}
diff --git a/extensions/RequestWhiner/Config.pm b/extensions/RequestWhiner/Config.pm
new file mode 100644
index 000000000..fb08bd7af
--- /dev/null
+++ b/extensions/RequestWhiner/Config.pm
@@ -0,0 +1,33 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the RequestWhiner Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Gervase Markham
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <written.to.the.glory.of.god@gerv.net>
+
+package Bugzilla::Extension::RequestWhiner;
+use strict;
+
+use constant NAME => 'RequestWhiner';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME; \ No newline at end of file
diff --git a/extensions/RequestWhiner/Extension.pm b/extensions/RequestWhiner/Extension.pm
new file mode 100644
index 000000000..3f1ee1f27
--- /dev/null
+++ b/extensions/RequestWhiner/Extension.pm
@@ -0,0 +1,43 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the RequestWhiner Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <written.to.the.glory.of.god@gerv.net>
+
+package Bugzilla::Extension::RequestWhiner;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Constants qw(bz_locations);
+use Bugzilla::Install::Filesystem;
+
+our $VERSION = '0.01';
+
+sub install_filesystem {
+ my ($self, $args) = @_;
+ my $files = $args->{'files'};
+
+ my $extensionsdir = bz_locations()->{'extensionsdir'};
+ my $scriptname = $extensionsdir . "/" . __PACKAGE__->NAME . "/bin/whineatrequests.pl";
+
+ $files->{$scriptname} = {
+ perms => Bugzilla::Install::Filesystem::WS_EXECUTE
+ };
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/RequestWhiner/bin/whineatrequests.pl b/extensions/RequestWhiner/bin/whineatrequests.pl
new file mode 100755
index 000000000..f7cb61dbb
--- /dev/null
+++ b/extensions/RequestWhiner/bin/whineatrequests.pl
@@ -0,0 +1,155 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Erik Stambaugh <erik@dasbistro.com>
+# Gervase Markham <gerv@gerv.net>
+
+use strict;
+
+BEGIN {
+ use lib qw(lib .);
+ use Bugzilla;
+ Bugzilla->extensions;
+}
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::User;
+use Bugzilla::Mailer;
+use Email::MIME;
+
+use Bugzilla::Extension::RequestWhiner::Constants;
+
+my $dbh = Bugzilla->dbh;
+
+my $sth_get_requests =
+ $dbh->prepare("SELECT profiles.login_name,
+ flagtypes.name,
+ flags.attach_id,
+ bugs.bug_id,
+ bugs.short_desc, " .
+ $dbh->sql_to_days('NOW()') .
+ " - " .
+ $dbh->sql_to_days('flags.modification_date') . "
+ AS age_in_days
+ FROM flags
+ JOIN bugs ON bugs.bug_id = flags.bug_id,
+ flagtypes,
+ profiles
+ WHERE flags.status = '?'
+ AND flags.requestee_id = profiles.userid
+ AND flags.type_id = flagtypes.id
+ AND " . $dbh->sql_to_days('NOW()') .
+ " - " .
+ $dbh->sql_to_days('flags.modification_date') .
+ " > " .
+ WHINE_AFTER_DAYS . "
+ ORDER BY flags.modification_date");
+
+$sth_get_requests->execute();
+
+# Build data structure
+my $requests = {};
+
+while (my ($login_name,
+ $flag_name,
+ $attach_id,
+ $bug_id,
+ $short_desc,
+ $age_in_days) = $sth_get_requests->fetchrow_array())
+{
+ if (!defined($requests->{$login_name})) {
+ $requests->{$login_name} = {};
+ }
+
+ if (!defined($requests->{$login_name}->{$flag_name})) {
+ $requests->{$login_name}->{$flag_name} = [];
+ }
+
+ push(@{ $requests->{$login_name}->{$flag_name} }, {
+ bug_id => $bug_id,
+ attach_id => $attach_id,
+ summary => $short_desc,
+ age => $age_in_days
+ });
+}
+
+$sth_get_requests->finish();
+
+foreach my $recipient (keys %$requests) {
+ my $user = new Bugzilla::User({ name => $recipient });
+
+ next if $user->email_disabled;
+
+ mail({
+ from => Bugzilla->params->{'mailfrom'},
+ recipient => $user,
+ subject => "Your Outstanding Requests",
+ requests => $requests->{$recipient},
+ threshold => WHINE_AFTER_DAYS
+ });
+}
+
+exit;
+
+###############################################################################
+# Functions
+#
+# Note: this function is exactly the same as the one in whine.pl, just using
+# different templates for the messages themselves.
+###############################################################################
+sub mail {
+ my $args = shift;
+ my $addressee = $args->{recipient};
+ my $template = Bugzilla->template;
+ my ($content, @parts);
+
+ $template->process("requestwhiner/mail.txt.tmpl", $args, \$content)
+ || die($template->error());
+ push(@parts, Email::MIME->create(
+ attributes => {
+ content_type => "text/plain",
+ },
+ body => $content,
+ ));
+
+ $content = '';
+ $template->process("requestwhiner/mail.html.tmpl", $args, \$content)
+ || die($template->error());
+
+ push(@parts, Email::MIME->create(
+ attributes => {
+ content_type => "text/html",
+ },
+ body => $content,
+ ));
+
+ $content = '';
+ $template->process("requestwhiner/header.txt.tmpl", $args, \$content)
+ || die($template->error());
+
+ # TT trims the trailing newline
+ my $email = new Email::MIME("$content\n");
+ $email->content_type_set('multipart/alternative');
+ $email->parts_set(\@parts);
+
+ MessageToMTA($email);
+}
diff --git a/extensions/RequestWhiner/lib/Constants.pm b/extensions/RequestWhiner/lib/Constants.pm
new file mode 100644
index 000000000..0e24ae1f0
--- /dev/null
+++ b/extensions/RequestWhiner/lib/Constants.pm
@@ -0,0 +1,31 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the RequestWhiner Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <written.to.the.glory.of.god@gerv.net>
+
+package Bugzilla::Extension::RequestWhiner::Constants;
+use strict;
+use base qw(Exporter);
+our @EXPORT = qw(
+ WHINE_AFTER_DAYS
+);
+
+use constant WHINE_AFTER_DAYS => 7;
+
+1;
diff --git a/extensions/RequestWhiner/template/en/default/requestwhiner/header.txt.tmpl b/extensions/RequestWhiner/template/en/default/requestwhiner/header.txt.tmpl
new file mode 100644
index 000000000..390fd3e2f
--- /dev/null
+++ b/extensions/RequestWhiner/template/en/default/requestwhiner/header.txt.tmpl
@@ -0,0 +1,6 @@
+[% PROCESS global/variables.none.tmpl %]
+From: [% from %]
+To: [% recipient.email %]
+Subject: [[% terms.Bugzilla %]] [% subject %]
+X-Bugzilla-Type: whine
+
diff --git a/extensions/RequestWhiner/template/en/default/requestwhiner/mail.html.tmpl b/extensions/RequestWhiner/template/en/default/requestwhiner/mail.html.tmpl
new file mode 100644
index 000000000..07b2b31ee
--- /dev/null
+++ b/extensions/RequestWhiner/template/en/default/requestwhiner/mail.html.tmpl
@@ -0,0 +1,62 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the RequestWhiner Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Gervase Markham
+ # Portions created by the Initial Developer are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <written.to.the.glory.of.god@gerv.net>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% PROCESS 'global/field-descs.none.tmpl' %]
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>
+ [[% terms.Bugzilla %]] [% subject FILTER html %]
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF">
+
+<p>The following is a list of requests people have made of you, which have been
+outstanding more than [% threshold FILTER html %] days. To avoid disappointing
+others, please deal with them as quickly as possible.
+(<a href="https://wiki.mozilla.org/BMO/Handling_Requests">Here is some
+guidance on handling requests</a>.)
+</p>
+
+[% FOREACH request_type = requests.keys %]
+<h3>[% request_type FILTER html %]</h3>
+
+<ul>
+ [% FOREACH request = requests.$request_type %]
+ <li>
+ <a href="[% urlbase FILTER none %]show_bug.cgi?id=[% request.bug_id FILTER none %]">[% terms.Bug %]
+ [%+ request.bug_id FILTER none %]: [% request.summary FILTER html %]</a> ([% request.age FILTER none %] days old)
+ [% IF request.attach_id %]
+ <br>
+ <small>(<a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attach_id FILTER none %]&action=edit">Details</a> |
+ <a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attach_id FILTER none %]&action=diff">Diff</a> |
+ <a href="[% urlbase FILTER none %]page.cgi?id=splinter.html&bug=[% request.bug_id FILTER none %]&attachment=[% request.attach_id FILTER none %]">Splinter Review</a>)</small>
+ [% END %]
+ </li>
+ [% END %]
+</ul>
+
+[% END %]
+
+<p><a href="[% urlbase FILTER none %]request.cgi?action=queue&requestee=[% recipient.email FILTER uri %]&group=type">See all your outstanding requests</a>.</p>
+
+ </body>
+</html>
diff --git a/extensions/RequestWhiner/template/en/default/requestwhiner/mail.txt.tmpl b/extensions/RequestWhiner/template/en/default/requestwhiner/mail.txt.tmpl
new file mode 100644
index 000000000..ef21563c9
--- /dev/null
+++ b/extensions/RequestWhiner/template/en/default/requestwhiner/mail.txt.tmpl
@@ -0,0 +1,41 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the RequestWhiner Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Gervase Markham
+ # Portions created by the Initial Developer are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <written.to.the.glory.of.god@gerv.net>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% PROCESS 'global/field-descs.none.tmpl' %]
+
+The following is a list of requests people have made of you, which have been
+outstanding more than [% threshold %] days. To avoid disappointing others, please deal with
+them as quickly as possible. Here is some guidance on handling requests:
+ https://wiki.mozilla.org/BMO/Handling_Requests
+
+[% FOREACH request_type = requests.keys %]
+[%+ request_type +%]
+[%+ "-" FILTER repeat(request_type.length) +%]
+
+ [% FOREACH request = requests.$request_type %]
+ [%+ terms.Bug +%] [%+ request.bug_id %]: [% request.summary +%] ([% request.age %] days old)
+ [%+ urlbase %]show_bug.cgi?id=[% request.bug_id +%]
+ [% IF request.attach_id %]
+ [%+ urlbase %]attachment.cgi?id=[% request.attach_id %]&action=edit
+ [% END %]
+ [%+ END +%]
+[% END %]
+To see all your outstanding requests, visit:
+[%+ urlbase %]request.cgi?action=queue&requestee=[% recipient.email FILTER url %]&group=type
diff --git a/extensions/RestrictComments/Config.pm b/extensions/RestrictComments/Config.pm
new file mode 100644
index 000000000..bef472cc1
--- /dev/null
+++ b/extensions/RestrictComments/Config.pm
@@ -0,0 +1,16 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::RestrictComments;
+
+use strict;
+
+use constant NAME => 'RestrictComments';
+use constant REQUIRED_MODULES => [];
+use constant OPTIONAL_MODULES => [];
+
+__PACKAGE__->NAME;
diff --git a/extensions/RestrictComments/Extension.pm b/extensions/RestrictComments/Extension.pm
new file mode 100644
index 000000000..001332a8e
--- /dev/null
+++ b/extensions/RestrictComments/Extension.pm
@@ -0,0 +1,95 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::RestrictComments;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Constants;
+
+BEGIN {
+ *Bugzilla::Bug::restrict_comments = \&_bug_restrict_comments;
+}
+
+sub _bug_restrict_comments {
+ my ($self) = @_;
+ return $self->{restrict_comments};
+}
+
+sub bug_check_can_change_field {
+ my ($self, $args) = @_;
+ my ($bug, $priv_results) = @$args{qw(bug priv_results)};
+ my $user = Bugzilla->user;
+
+ if ($user->id
+ && $bug->restrict_comments
+ && !$user->in_group(Bugzilla->params->{'restrict_comments_group'}))
+ {
+ push(@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ return;
+ }
+}
+
+sub _can_restrict_comments {
+ my ($self, $object) = @_;
+ return unless $object->isa('Bugzilla::Bug');
+ $self->{setter_group} ||= Bugzilla->params->{'restrict_comments_enable_group'};
+ return Bugzilla->user->in_group($self->{setter_group});
+}
+
+sub object_end_of_set_all {
+ my ($self, $args) = @_;
+ my $object = $args->{object};
+ if ($self->_can_restrict_comments($object)) {
+ my $input = Bugzilla->input_params;
+ $object->set('restrict_comments', $input->{restrict_comments} ? 1 : undef);
+ }
+}
+
+sub object_update_columns {
+ my ($self, $args) = @_;
+ my ($object, $columns) = @$args{qw(object columns)};
+ if ($self->_can_restrict_comments($object)) {
+ push(@$columns, 'restrict_comments');
+ }
+}
+
+sub object_columns {
+ my ($self, $args) = @_;
+ my ($class, $columns) = @$args{qw(class columns)};
+ if ($class->isa('Bugzilla::Bug')) {
+ push(@$columns, 'restrict_comments');
+ }
+}
+
+sub bug_fields {
+ my ($self, $args) = @_;
+ my $fields = $args->{'fields'};
+ push (@$fields, 'restrict_comments')
+}
+
+sub config_add_panels {
+ my ($self, $args) = @_;
+ my $modules = $args->{panel_modules};
+ $modules->{RestrictComments} = "Bugzilla::Extension::RestrictComments::Config";
+}
+
+sub install_update_db {
+ my $dbh = Bugzilla->dbh;
+
+ my $field = new Bugzilla::Field({ name => 'restrict_comments' });
+ if (!$field) {
+ Bugzilla::Field->create({ name => 'restrict_comments', description => 'Restrict Comments' });
+ }
+
+ $dbh->bz_add_column('bugs', 'restrict_comments', { TYPE => 'BOOLEAN' });
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/RestrictComments/lib/Config.pm b/extensions/RestrictComments/lib/Config.pm
new file mode 100644
index 000000000..33607e680
--- /dev/null
+++ b/extensions/RestrictComments/lib/Config.pm
@@ -0,0 +1,47 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::RestrictComments::Config;
+
+use strict;
+use warnings;
+
+use Bugzilla::Config::Common;
+use Bugzilla::Group;
+
+our $sortkey = 510;
+
+sub get_param_list {
+ my ($class) = @_;
+
+ my @param_list = (
+ {
+ name => 'restrict_comments_group',
+ type => 's',
+ choices => \&_get_all_group_names,
+ default => '',
+ checker => \&check_group
+ },
+ {
+ name => 'restrict_comments_enable_group',
+ type => 's',
+ choices => \&_get_all_group_names,
+ default => '',
+ checker => \&check_group
+ },
+ );
+
+ return @param_list;
+}
+
+sub _get_all_group_names {
+ my @group_names = map {$_->name} Bugzilla::Group->get_all;
+ unshift(@group_names, '');
+ return \@group_names;
+}
+
+1;
diff --git a/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl b/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl
new file mode 100644
index 000000000..d2a050563
--- /dev/null
+++ b/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl
@@ -0,0 +1,23 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ title = "Restrict Comments"
+ desc = "Edit Restrict Comments Configuration"
+%]
+
+[% param_descs =
+{
+ restrict_comments_group => "Users must be a member of this group to " _
+ "comment on bug with restricted commenting " _
+ "enabled."
+
+ restrict_comments_enable_group => "Members of this group can toggle " _
+ "'restrict comments' on bugs."
+}
+%]
diff --git a/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl b/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl
new file mode 100644
index 000000000..c5250c8c2
--- /dev/null
+++ b/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl
@@ -0,0 +1,26 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+
+[% RETURN UNLESS user.in_group(Param('restrict_comments_enable_group')) %]
+
+[%# using a table to match alignment of the needinfo checkboxes %]
+<table>
+<tr>
+ <td>
+ <input type="checkbox" name="restrict_comments" id="restrict_comments"
+ [% " checked" IF bug.restrict_comments %]>
+ <label for="restrict_comments">
+ Restrict commenting on this [% terms.bug %] to users in the
+ <b>[% Param('restrict_comments_group') FILTER html %]</b> group.
+ </label>
+ (<a href="page.cgi?id=restrict_comments_guidelines.html"
+ target="_blank">guidelines</a>)
+ </td>
+</tr>
+</table>
diff --git a/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl b/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl
new file mode 100644
index 000000000..694681ad7
--- /dev/null
+++ b/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl
@@ -0,0 +1,62 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% USE Bugzilla %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Restrict Comments - Guidelines"
+%]
+
+<h3>Restricting Comments</h3>
+
+<p>
+ Some [% terms.bug %] reports are inundated with comments that make it
+ difficult for developers to conduct technical discussions. Restricting
+ comments provides the ability for users in the
+ [%+ Param('restrict_comments_enable_group') FILTER html %] group to prevent
+ users who are not in the [% Param('restrict_comments_group') FILTER html %]
+ from making additional comments.
+</p>
+
+<h3>Guidelines</h3>
+
+<ul>
+ <li>
+ Restrictions may be applied to [% terms.bugs %] which are subject to high
+ volumes of off topic comments, or [% terms.bugs %] which contain high volumes
+ of violations of [% terms.Bugzilla %]
+ <a href="page.cgi?id=etiquette.html">etiquette guidelines</a>.
+ </li>
+ <li>
+ Restrictions should not be used as a preemptive measure against comments
+ which have not yet occurred.
+ </li>
+ <li>
+ Restrictions should not be used to privilege
+ [%+ Param('restrict_comments_group') FILTER html %] users over other users
+ in valid disputes/discussions.
+ </li>
+</ul>
+
+<h3>Impact</h3>
+
+<ul>
+ <li>
+ Users who are not in the [% Param('restrict_comments_group') FILTER html %]
+ group will not be able to comment on the [% terms.bug %], nor will they be
+ able to change the value of any field.
+ </li>
+ <li>
+ All users will still be able to CC themselves to the [% terms.bug %].
+ </li>
+ <li>
+ All users will still be able to vote for the [% terms.bug %].
+ </li>
+</ul>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/SecureMail/Config.pm b/extensions/SecureMail/Config.pm
new file mode 100644
index 000000000..5b53ddf67
--- /dev/null
+++ b/extensions/SecureMail/Config.pm
@@ -0,0 +1,47 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla SecureMail Extension
+#
+# The Initial Developer of the Original Code is Mozilla.
+# Portions created by Mozilla are Copyright (C) 2008 Mozilla Corporation.
+# All Rights Reserved.
+#
+# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::SecureMail;
+use strict;
+
+use constant NAME => 'SecureMail';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'Crypt-OpenPGP',
+ module => 'Crypt::OpenPGP',
+ # 1.02 added the ability for new() to take KeyRing objects for the
+ # PubRing argument.
+ version => '1.02',
+ },
+ {
+ package => 'Crypt-SMIME',
+ module => 'Crypt::SMIME',
+ version => 0,
+ },
+ {
+ package => 'HTML-Tree',
+ module => 'HTML::Tree',
+ version => 0,
+ }
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/SecureMail/Extension.pm b/extensions/SecureMail/Extension.pm
new file mode 100644
index 000000000..1ea691320
--- /dev/null
+++ b/extensions/SecureMail/Extension.pm
@@ -0,0 +1,627 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla SecureMail Extension
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by Mozilla are Copyright (C) 2008 Mozilla Foundation.
+# All Rights Reserved.
+#
+# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::SecureMail;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Attachment;
+use Bugzilla::Comment;
+use Bugzilla::Group;
+use Bugzilla::Object;
+use Bugzilla::User;
+use Bugzilla::Util qw(correct_urlbase trim trick_taint is_7bit_clean);
+use Bugzilla::Error;
+use Bugzilla::Mailer;
+
+use Crypt::OpenPGP::Armour;
+use Crypt::OpenPGP::KeyRing;
+use Crypt::OpenPGP;
+use Crypt::SMIME;
+use Encode;
+use HTML::Tree;
+
+our $VERSION = '0.5';
+
+use constant SECURE_NONE => 0;
+use constant SECURE_BODY => 1;
+use constant SECURE_ALL => 2;
+
+##############################################################################
+# Creating new columns
+#
+# secure_mail boolean in the 'groups' table - whether to send secure mail
+# public_key text in the 'profiles' table - stores public key
+##############################################################################
+sub install_update_db {
+ my ($self, $args) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ $dbh->bz_add_column('groups', 'secure_mail',
+ {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
+ $dbh->bz_add_column('profiles', 'public_key', { TYPE => 'LONGTEXT' });
+}
+
+##############################################################################
+# Maintaining new columns
+##############################################################################
+
+BEGIN {
+ *Bugzilla::Group::secure_mail = \&_secure_mail;
+}
+
+sub _secure_mail { return $_[0]->{'secure_mail'}; }
+
+# Make sure generic functions know about the additional fields in the user
+# and group objects.
+sub object_columns {
+ my ($self, $args) = @_;
+ my $class = $args->{'class'};
+ my $columns = $args->{'columns'};
+
+ if ($class->isa('Bugzilla::Group')) {
+ push(@$columns, 'secure_mail');
+ }
+ elsif ($class->isa('Bugzilla::User')) {
+ push(@$columns, 'public_key');
+ }
+}
+
+# Plug appropriate validators so we can check the validity of the two
+# fields created by this extension, when new values are submitted.
+sub object_validators {
+ my ($self, $args) = @_;
+ my %args = %{ $args };
+ my ($invocant, $validators) = @args{qw(class validators)};
+
+ if ($invocant->isa('Bugzilla::Group')) {
+ $validators->{'secure_mail'} = \&Bugzilla::Object::check_boolean;
+ }
+ elsif ($invocant->isa('Bugzilla::User')) {
+ $validators->{'public_key'} = sub {
+ my ($self, $value) = @_;
+ $value = trim($value) || '';
+
+ return $value if $value eq '';
+
+ if ($value =~ /PUBLIC KEY/) {
+ # PGP keys must be ASCII-armoured.
+ if (!Crypt::OpenPGP::Armour->unarmour($value)) {
+ ThrowUserError('securemail_invalid_key',
+ { errstr => Crypt::OpenPGP::Armour->errstr });
+ }
+ }
+ elsif ($value =~ /BEGIN CERTIFICATE/) {
+ # S/MIME Keys must be in PEM format (Base64-encoded X.509)
+ #
+ # Crypt::SMIME seems not to like tainted values - it claims
+ # they aren't scalars!
+ trick_taint($value);
+
+ my $smime = Crypt::SMIME->new();
+ eval {
+ $smime->setPublicKey([$value]);
+ };
+ if ($@) {
+ ThrowUserError('securemail_invalid_key',
+ { errstr => $@ });
+ }
+ }
+ else {
+ ThrowUserError('securemail_invalid_key');
+ }
+
+ return $value;
+ };
+ }
+}
+
+# When creating a 'group' object, set up the secure_mail field appropriately.
+sub object_before_create {
+ my ($self, $args) = @_;
+ my $class = $args->{'class'};
+ my $params = $args->{'params'};
+
+ if ($class->isa('Bugzilla::Group')) {
+ $params->{secure_mail} = Bugzilla->cgi->param('secure_mail');
+ }
+}
+
+# On update, make sure the updating process knows about our new columns.
+sub object_update_columns {
+ my ($self, $args) = @_;
+ my $object = $args->{'object'};
+ my $columns = $args->{'columns'};
+
+ if ($object->isa('Bugzilla::Group')) {
+ # This seems like a convenient moment to extract this value...
+ $object->set('secure_mail', Bugzilla->cgi->param('secure_mail'));
+
+ push(@$columns, 'secure_mail');
+ }
+ elsif ($object->isa('Bugzilla::User')) {
+ push(@$columns, 'public_key');
+ }
+}
+
+# Handle the setting and changing of the public key.
+sub user_preferences {
+ my ($self, $args) = @_;
+ my $tab = $args->{'current_tab'};
+ my $save = $args->{'save_changes'};
+ my $handled = $args->{'handled'};
+ my $vars = $args->{'vars'};
+ my $params = Bugzilla->input_params;
+
+ return unless $tab eq 'securemail';
+
+ # Create a new user object so we don't mess with the main one, as we
+ # don't know where it's been...
+ my $user = new Bugzilla::User(Bugzilla->user->id);
+
+ if ($save) {
+ $user->set('public_key', $params->{'public_key'});
+ $user->update();
+
+ # Send user a test email
+ if ($user->{'public_key'}) {
+ _send_test_email($user);
+ $vars->{'test_email_sent'} = 1;
+ }
+ }
+
+ $vars->{'public_key'} = $user->{'public_key'};
+
+ # Set the 'handled' scalar reference to true so that the caller
+ # knows the panel name is valid and that an extension took care of it.
+ $$handled = 1;
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ # Bug dependency emails contain the subject of the dependent bug
+ # right before the diffs when a status has gone from open/closed
+ # or closed/open. We need to sanitize the subject of change.blocker
+ # similar to how we do referenced bugs
+ return unless
+ $file eq 'email/bugmail.html.tmpl'
+ || $file eq 'email/bugmail.txt.tmpl';
+
+ if (defined $vars->{diffs}) {
+ foreach my $change (@{ $vars->{diffs} }) {
+ next if !defined $change->{blocker};
+ if (grep($_->secure_mail, @{ $change->{blocker}->groups_in })) {
+ $change->{blocker}->{short_desc} = "(Secure bug)";
+ }
+ }
+ }
+}
+
+sub _send_test_email {
+ my ($user) = @_;
+ my $template = Bugzilla->template_inner($user->settings->{'lang'}->{'value'});
+
+ my $vars = {
+ to_user => $user->email,
+ };
+
+ my $msg = "";
+ $template->process("account/email/securemail-test.txt.tmpl", $vars, \$msg)
+ || ThrowTemplateError($template->error());
+
+ MessageToMTA($msg);
+}
+
+##############################################################################
+# Encrypting the email
+##############################################################################
+sub mailer_before_send {
+ my ($self, $args) = @_;
+
+ my $email = $args->{'email'};
+ my $body = $email->body;
+
+ # Decide whether to make secure.
+ # This is a bit of a hack; it would be nice if it were more clear
+ # what sort a particular email is.
+ my $is_bugmail = $email->header('X-Bugzilla-Status') ||
+ $email->header('X-Bugzilla-Type') eq 'request';
+ my $is_passwordmail = !$is_bugmail && ($body =~ /cfmpw.*cxlpw/s);
+ my $is_test_email = $email->header('X-Bugzilla-Type') =~ /securemail-test/ ? 1 : 0;
+ my $is_whine_email = $email->header('X-Bugzilla-Type') eq 'whine' ? 1 : 0;
+
+ if ($is_bugmail || $is_passwordmail || $is_test_email || $is_whine_email) {
+ # Convert the email's To address into a User object
+ my $login = $email->header('To');
+ my $emailsuffix = Bugzilla->params->{'emailsuffix'};
+ $login =~ s/$emailsuffix$//;
+ my $user = new Bugzilla::User({ name => $login });
+
+ # Default to secure. (Of course, this means if this extension has a
+ # bug, lots of people are going to get bugmail falsely claiming their
+ # bugs are secure and they need to add a key...)
+ my $make_secure = SECURE_ALL;
+
+ if ($is_bugmail) {
+ # This is also a bit of a hack, but there's no header with the
+ # bug ID in. So we take the first number in the subject.
+ my ($bug_id) = ($email->header('Subject') =~ /\[\D+(\d+)\]/);
+ my $bug = new Bugzilla::Bug($bug_id);
+ if (!_should_secure_bug($bug)) {
+ $make_secure = SECURE_NONE;
+ }
+ # If the insider group has securemail enabled..
+ my $insider_group = Bugzilla::Group->new({ name => Bugzilla->params->{'insidergroup'} });
+ if ($insider_group->secure_mail && $make_secure == SECURE_NONE) {
+ my $comment_is_private = Bugzilla->dbh->selectcol_arrayref(
+ "SELECT isprivate FROM longdescs WHERE bug_id=? ORDER BY bug_when",
+ undef, $bug_id);
+ # Encrypt if there are private comments on an otherwise public bug
+ while ($body =~ /[\r\n]--- Comment #(\d+)/g) {
+ my $comment_number = $1;
+ if ($comment_number && $comment_is_private->[$comment_number]) {
+ $make_secure = SECURE_BODY;
+ last;
+ }
+ }
+ # Encrypt if updating a private attachment without a comment
+ if ($email->header('X-Bugzilla-Changed-Fields')
+ && $email->header('X-Bugzilla-Changed-Fields') =~ /Attachment #(\d+)/)
+ {
+ my $attachment = Bugzilla::Attachment->new($1);
+ if ($attachment && $attachment->isprivate) {
+ $make_secure = SECURE_BODY;
+ }
+ }
+ }
+ }
+ elsif ($is_passwordmail) {
+ # Mail is made unsecure only if the user does not have a public
+ # key and is not in any security groups. So specifying a public
+ # key OR being in a security group means the mail is kept secure
+ # (but, as noted above, the check is the other way around because
+ # we default to secure).
+ if ($user &&
+ !$user->{'public_key'} &&
+ !grep($_->secure_mail, @{ $user->groups }))
+ {
+ $make_secure = SECURE_NONE;
+ }
+ }
+ elsif ($is_whine_email) {
+ # When a whine email has one or more secure bugs in the body, then
+ # encrypt the entire email body. Subject can be left alone as it
+ # comes from the whine settings.
+ $make_secure = _should_secure_whine($email) ? SECURE_BODY : SECURE_NONE;
+ }
+
+ # If finding the user fails for some reason, but we determine we
+ # should be encrypting, we want to make the mail safe. An empty key
+ # does that.
+ my $public_key = $user ? $user->{'public_key'} : '';
+
+ # Check if the new bugmail prefix should be added to the subject.
+ my $add_new = ($email->header('X-Bugzilla-Type') eq 'new' &&
+ $user &&
+ $user->settings->{'bugmail_new_prefix'}->{'value'} eq 'on') ? 1 : 0;
+
+ if ($make_secure == SECURE_NONE) {
+ # Filter the bug_links in HTML email in case the bugs the links
+ # point are "secured" bugs and the user may not be able to see
+ # the summaries.
+ _filter_bug_links($email);
+ }
+ else {
+ _make_secure($email, $public_key, $is_bugmail && $make_secure == SECURE_ALL, $add_new);
+ }
+ }
+}
+
+# Custom hook for bugzilla.mozilla.org (see bug 752400)
+sub bugmail_referenced_bugs {
+ my ($self, $args) = @_;
+ # Sanitise subjects of referenced bugs.
+ my $referenced_bugs = $args->{'referenced_bugs'};
+ # No need to sanitise subjects if the entire email will be secured.
+ return if _should_secure_bug($args->{'updated_bug'});
+ # Replace the subject if required
+ foreach my $ref (@$referenced_bugs) {
+ if (grep($_->secure_mail, @{ $ref->{'bug'}->groups_in })) {
+ $ref->{'short_desc'} = "(Secure bug)";
+ }
+ }
+}
+
+sub _should_secure_bug {
+ my ($bug) = @_;
+ # If there's a problem with the bug, err on the side of caution and mark it
+ # as secure.
+ return
+ !$bug
+ || $bug->{'error'}
+ || grep($_->secure_mail, @{ $bug->groups_in });
+}
+
+sub _should_secure_whine {
+ my ($email) = @_;
+ my $should_secure = 0;
+ $email->walk_parts(sub {
+ my $part = shift;
+ my $content_type = $part->content_type;
+ return if !$content_type || $content_type !~ /^text\/plain/;
+ my $body = $part->body;
+ my @bugids = $body =~ /Bug (\d+):/g;
+ foreach my $id (@bugids) {
+ $id = trim($id);
+ next if !$id;
+ my $bug = new Bugzilla::Bug($id);
+ if ($bug && _should_secure_bug($bug)) {
+ $should_secure = 1;
+ last;
+ }
+ }
+ });
+ return $should_secure ? 1 : 0;
+}
+
+sub _make_secure {
+ my ($email, $key, $sanitise_subject, $add_new) = @_;
+
+ my $subject = $email->header('Subject');
+ my ($bug_id) = $subject =~ /\[\D+(\d+)\]/;
+
+ my $key_type = 0;
+ if ($key && $key =~ /PUBLIC KEY/) {
+ $key_type = 'PGP';
+ }
+ elsif ($key && $key =~ /BEGIN CERTIFICATE/) {
+ $key_type = 'S/MIME';
+ }
+
+ if ($key_type eq 'PGP') {
+ ##################
+ # PGP Encryption #
+ ##################
+
+ my $pubring = new Crypt::OpenPGP::KeyRing(Data => $key);
+ my $pgp = new Crypt::OpenPGP(PubRing => $pubring);
+
+ if (scalar $email->parts > 1) {
+ my $old_boundary = $email->{ct}{attributes}{boundary};
+ my $to_encrypt = "Content-Type: " . $email->content_type . "\n\n";
+
+ # We need to do some fix up of each part for proper encoding and then
+ # stringify all parts for encrypting. We have to retain the old
+ # boundaries as well so that the email client can reconstruct the
+ # original message properly.
+ $email->walk_parts(\&_fix_part);
+
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ if ($sanitise_subject) {
+ _insert_subject($part, $subject);
+ }
+ return if $part->parts > 1; # Top-level
+ $to_encrypt .= "--$old_boundary\n" . $part->as_string . "\n";
+ });
+ $to_encrypt .= "--$old_boundary--";
+
+ # Now create the new properly formatted PGP parts containing the
+ # encrypted original message
+ my @new_parts = (
+ Email::MIME->create(
+ attributes => {
+ content_type => 'application/pgp-encrypted',
+ encoding => '7bit',
+ },
+ body => "Version: 1\n",
+ ),
+ Email::MIME->create(
+ attributes => {
+ content_type => 'application/octet-stream',
+ filename => 'encrypted.asc',
+ disposition => 'inline',
+ encoding => '7bit',
+ },
+ body => _pgp_encrypt($pgp, $to_encrypt)
+ ),
+ );
+ $email->parts_set(\@new_parts);
+ my $new_boundary = $email->{ct}{attributes}{boundary};
+ # Redo the old content type header with the new boundaries
+ # and other information needed for PGP
+ $email->header_set("Content-Type",
+ "multipart/encrypted; " .
+ "protocol=\"application/pgp-encrypted\"; " .
+ "boundary=\"$new_boundary\"");
+ }
+ else {
+ _fix_part($email);
+ if ($sanitise_subject) {
+ _insert_subject($email, $subject);
+ }
+ $email->body_set(_pgp_encrypt($pgp, $email->body));
+ }
+ }
+
+ elsif ($key_type eq 'S/MIME') {
+ #####################
+ # S/MIME Encryption #
+ #####################
+
+ $email->walk_parts(\&_fix_part);
+
+ if ($sanitise_subject) {
+ $email->walk_parts(sub { _insert_subject($_[0], $subject) });
+ }
+
+ my $smime = Crypt::SMIME->new();
+ my $encrypted;
+
+ eval {
+ $smime->setPublicKey([$key]);
+ $encrypted = $smime->encrypt($email->as_string());
+ };
+
+ if (!$@) {
+ # We can't replace the Email::MIME object, so we have to swap
+ # out its component parts.
+ my $enc_obj = new Email::MIME($encrypted);
+ $email->header_obj_set($enc_obj->header_obj());
+ $email->parts_set([]);
+ $email->body_set($enc_obj->body());
+ $email->content_type_set('application/pkcs7-mime');
+ $email->charset_set('UTF-8') if Bugzilla->params->{'utf8'};
+ }
+ else {
+ $email->body_set('Error during Encryption: ' . $@);
+ }
+ }
+ else {
+ # No encryption key provided; send a generic, safe email.
+ my $template = Bugzilla->template;
+ my $message;
+ my $vars = {
+ 'urlbase' => correct_urlbase(),
+ 'bug_id' => $bug_id,
+ 'maintainer' => Bugzilla->params->{'maintainer'}
+ };
+
+ $template->process('account/email/encryption-required.txt.tmpl',
+ $vars, \$message)
+ || ThrowTemplateError($template->error());
+
+ $email->parts_set([]);
+ $email->content_type_set('text/plain');
+ $email->body_set($message);
+ }
+
+ if ($sanitise_subject) {
+ # This is designed to still work if the admin changes the word
+ # 'bug' to something else. However, it could break if they change
+ # the format of the subject line in another way.
+ my $new = $add_new ? ' New:' : '';
+ $subject =~ s/($bug_id\])\s+(.*)$/$1$new (Secure bug $bug_id updated)/;
+ $email->header_set('Subject', $subject);
+ }
+}
+
+sub _pgp_encrypt {
+ my ($pgp, $text) = @_;
+ # "@" matches every key in the public key ring, which is fine,
+ # because there's only one key in our keyring.
+ #
+ # We use the CAST5 cipher because the Rijndael (AES) module doesn't
+ # like us for some reason I don't have time to debug fully.
+ # ("key must be an untainted string scalar")
+ my $encrypted = $pgp->encrypt(Data => $text,
+ Recipients => "@",
+ Cipher => 'CAST5',
+ Armour => 1);
+ if (!defined $encrypted) {
+ return 'Error during Encryption: ' . $pgp->errstr;
+ }
+ return $encrypted;
+}
+
+# Insert the subject into the part's body, as the subject of the message will
+# be sanitised.
+# XXX this incorrectly assumes all parts of the message are the body
+# we should only alter parts who's parent is multipart/alternative
+sub _insert_subject {
+ my ($part, $subject) = @_;
+ my $content_type = $part->content_type or return;
+ if ($content_type =~ /^text\/plain/) {
+ if (!is_7bit_clean($subject)) {
+ $part->encoding_set('quoted-printable');
+ }
+ $part->body_str_set("Subject: $subject\015\012\015\012" . $part->body_str);
+ }
+ elsif ($content_type =~ /^text\/html/) {
+ my $tree = HTML::Tree->new->parse_content($part->body_str);
+ my $body = $tree->look_down(qw(_tag body));
+ $body->unshift_content(['div', "Subject: $subject"], ['br']);
+ _set_body_from_tree($part, $tree);
+ }
+}
+
+# Copied from Bugzilla/Mailer as this extension runs before
+# this code there and Mailer.pm will no longer see the original
+# message.
+sub _fix_part {
+ my ($part) = @_;
+ return if $part->parts > 1; # Top-level
+ my $content_type = $part->content_type || '';
+ $content_type =~ /charset=['"](.+)['"]/;
+ # If no charset is defined or is the default us-ascii,
+ # then we encode the email to UTF-8 if Bugzilla has utf8 enabled.
+ # XXX - This is a hack to workaround bug 723944.
+ if (!$1 || $1 eq 'us-ascii') {
+ my $body = $part->body;
+ if (Bugzilla->params->{'utf8'}) {
+ $part->charset_set('UTF-8');
+ # encoding_set works only with bytes, not with utf8 strings.
+ my $raw = $part->body_raw;
+ if (utf8::is_utf8($raw)) {
+ utf8::encode($raw);
+ $part->body_set($raw);
+ }
+ }
+ $part->encoding_set('quoted-printable') if !is_7bit_clean($body);
+ }
+}
+
+sub _filter_bug_links {
+ my ($email) = @_;
+ $email->walk_parts(sub {
+ my $part = shift;
+ my $content_type = $part->content_type;
+ return if !$content_type || $content_type !~ /text\/html/;
+ my $tree = HTML::Tree->new->parse_content($part->body);
+ my @links = $tree->look_down( _tag => q{a}, class => qr/bz_bug_link/ );
+ my $updated = 0;
+ foreach my $link (@links) {
+ my $href = $link->attr('href');
+ my ($bug_id) = $href =~ /\Qshow_bug.cgi?id=\E(\d+)/;
+ my $bug = new Bugzilla::Bug($bug_id);
+ if ($bug && _should_secure_bug($bug)) {
+ $link->attr('title', '(secure bug)');
+ $link->attr('class', 'bz_bug_link');
+ $updated = 1;
+ }
+ }
+ if ($updated) {
+ _set_body_from_tree($part, $tree);
+ }
+ });
+}
+
+sub _set_body_from_tree {
+ my ($part, $tree) = @_;
+ $part->body_set($tree->as_HTML);
+ $part->charset_set('UTF-8') if Bugzilla->params->{'utf8'};
+ $part->encoding_set('quoted-printable');
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/SecureMail/README b/extensions/SecureMail/README
new file mode 100644
index 000000000..ac3484291
--- /dev/null
+++ b/extensions/SecureMail/README
@@ -0,0 +1,8 @@
+This extension should be placed in a directory called "SecureMail" in the
+Bugzilla extensions/ directory. After installing it, remove the file
+"disabled" (if present) and then run checksetup.pl.
+
+Instructions for user key formats:
+
+S/MIME Keys must be in PEM format - i.e. Base64-encoded text, with BEGIN CERTIFICATE
+PGP keys must be ASCII-armoured - i.e. text, with BEGIN PGP PUBLIC KEY.
diff --git a/extensions/SecureMail/template/en/default/account/email/encryption-required.txt.tmpl b/extensions/SecureMail/template/en/default/account/email/encryption-required.txt.tmpl
new file mode 100644
index 000000000..7341992c8
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/account/email/encryption-required.txt.tmpl
@@ -0,0 +1,15 @@
+This email would have contained sensitive information, and you have not set
+a PGP/GPG key or SMIME certificate in the "Secure Mail" section of your user
+preferences.
+
+[% IF bug_id %]
+In order to receive the full text of similar mails in the future, please
+go to:
+[%+ urlbase %]userprefs.cgi?tab=securemail
+and provide a key or certificate.
+
+You can see this bug's current state at:
+[%+ urlbase %]show_bug.cgi?id=[% bug_id %]
+[% ELSE %]
+You will have to contact [% maintainer %] to reset your password.
+[% END %]
diff --git a/extensions/SecureMail/template/en/default/account/email/securemail-test.txt.tmpl b/extensions/SecureMail/template/en/default/account/email/securemail-test.txt.tmpl
new file mode 100644
index 000000000..e4f4c9242
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/account/email/securemail-test.txt.tmpl
@@ -0,0 +1,23 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+From: [% Param('mailfrom') %]
+To: [% to_user %]
+Subject: [% terms.Bugzilla %] SecureMail Test Email
+X-Bugzilla-Type: securemail-test
+
+Congratulations! If you can read this, then your SecureMail encryption
+key uploaded to [% terms.Bugzilla %] is working properly.
+
+To update your SecureMail preferences at any time, please go to:
+[%+ urlbase %]userprefs.cgi?tab=securemail
+
+Sincerely,
+Your Friendly [% terms.Bugzilla %] Administrator
diff --git a/extensions/SecureMail/template/en/default/account/prefs/securemail.html.tmpl b/extensions/SecureMail/template/en/default/account/prefs/securemail.html.tmpl
new file mode 100644
index 000000000..db595a23f
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/account/prefs/securemail.html.tmpl
@@ -0,0 +1,40 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Corporation.
+ # Portions created by the Initial Developer are Copyright (C) 2008 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+
+[% IF test_email_sent %]
+ <div id="message">
+ An encrypted test email has been sent to your address.
+ </div>
+[% END %]
+
+<p>Some [% terms.bugs %] in this [% terms.Bugzilla %] are in groups the administrator has
+deemed 'secure'. This means emails containing information about those [% terms.bugs %]
+will only be sent encrypted. Enter your PGP/GPG public key or
+SMIME certificate here to receive full update emails for such [% terms.bugs %].</p>
+
+<p>If you are a member of a secure group, or if you enter a key here, your password reset email will also be sent to you encrypted. If you are a member of a secure group and do not enter a key, you will not be able to reset your password without the assistance of an administrator.</p>
+
+<p><a href="page.cgi?id=securemail/help.html">More help is available</a>.</p>
+
+[% Hook.process('moreinfo') %]
+
+<textarea id="public_key" name="public_key" cols="72" rows="12">
+ [%- public_key FILTER html %]</textarea>
+
+<p>Submitting valid changes will automatically send an encrypted test email to your address.</p>
diff --git a/extensions/SecureMail/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl b/extensions/SecureMail/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl
new file mode 100644
index 000000000..70a40e592
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl
@@ -0,0 +1,28 @@
+[%# -*- Mode: perl; indent-tabs-mode: nil -*-
+ #
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla SecureMail Extension
+ #
+ # The Initial Developer of the Original Code is Mozilla.
+ # Portions created by Mozilla are Copyright (C) 2008 Mozilla Corporation.
+ # All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ # Gervase Markham <gerv@gerv.net>
+ #%]
+
+[% tabs = tabs.import([{
+ name => "securemail",
+ label => "Secure Mail",
+ link => "userprefs.cgi?tab=securemail",
+ saveable => 1
+ }]) %]
diff --git a/extensions/SecureMail/template/en/default/hook/admin/groups/create-field.html.tmpl b/extensions/SecureMail/template/en/default/hook/admin/groups/create-field.html.tmpl
new file mode 100644
index 000000000..27c644d02
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/hook/admin/groups/create-field.html.tmpl
@@ -0,0 +1,25 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Corporation.
+ # Portions created by the Initial Developer are Copyright (C) 2008 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+<tr>
+ <th>Secure Bugmail:</th>
+ <td colspan="3">
+ <input type="checkbox" id="secure_mail" name="secure_mail"
+ [% ' checked="checked"' IF group.secure_mail %]>
+ </td>
+</tr>
diff --git a/extensions/SecureMail/template/en/default/hook/admin/groups/edit-field.html.tmpl b/extensions/SecureMail/template/en/default/hook/admin/groups/edit-field.html.tmpl
new file mode 100644
index 000000000..253fed29e
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/hook/admin/groups/edit-field.html.tmpl
@@ -0,0 +1,27 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Corporation.
+ # Portions created by the Initial Developer are Copyright (C) 2008 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+[% IF group.is_bug_group || group.name == Param('insidergroup') %]
+ <tr>
+ <th>Secure Bugmail:</th>
+ <td>
+ <input type="checkbox" id="secure_mail" name="secure_mail"
+ [% ' checked="checked"' IF group.secure_mail %]>
+ </td>
+ </tr>
+[% END %]
diff --git a/extensions/SecureMail/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/SecureMail/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..46b093674
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,27 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Corporation.
+ # Portions created by the Initial Developer are Copyright (C) 2008 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+
+[% IF error == "securemail_invalid_key" %]
+ [% title = "Invalid Public Key" %]
+ We were unable to read the public key that you entered. Make sure
+ that you are entering either an ASCII-armored PGP/GPG public key,
+ including the "BEGIN PGP PUBLIC KEY BLOCK" and "END PGP PUBLIC KEY BLOCK"
+ lines, or a PEM format (Base64-encoded X.509) S/MIME key, including the
+ BEGIN CERTIFICATE and END CERTIFICATE lines.<br><br>[% errstr FILTER html %]
+[% END %]
diff --git a/extensions/SecureMail/template/en/default/pages/securemail/help.html.tmpl b/extensions/SecureMail/template/en/default/pages/securemail/help.html.tmpl
new file mode 100644
index 000000000..076b3e26c
--- /dev/null
+++ b/extensions/SecureMail/template/en/default/pages/securemail/help.html.tmpl
@@ -0,0 +1,98 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla SecureMail Extension.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation.
+ # Portions created by Mozilla are Copyright (C) 2008 Mozilla Foundation.
+ # All Rights Reserved.
+ #
+ # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+ # Gervase Markham <gerv@gerv.net>
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "SecureMail Help"
+%]
+
+[% terms.Bugzilla %] considers certain groups as "secure". If a [% terms.bug %] is in one of those groups, [% terms.Bugzilla %] will not send unencrypted
+email about it. To receive encrypted email rather than just a "something changed" placeholder, you must provide either
+a S/MIME or a GPG/PGP key on the <a href="[% urlbase FILTER none %]userprefs.cgi?tab=securemail">SecureMail preferences tab</a>.<br>
+<br>
+In addition, if you have uploaded a S/MIME or GPG/PGP key using the <a href="[% urlbase FILTER none %]userprefs.cgi?tab=securemail">
+SecureMail preferences tab</a>, if you request your password to be reset, [% terms.Bugzilla %] will send the reset email encrypted and you will
+be required to decrypt it to view the reset instructions.
+
+<h2>S/MIME</h2>
+
+<b>S/MIME Keys must be in PEM format - i.e. Base64-encoded text, with the first line containing BEGIN CERTIFICATE.</b></p>
+
+<p>
+S/MIME certificates can be obtained from a number of providers. You can get a free one from <a href="https://www.startssl.com/?app=12">StartCom</a>.
+Once you have it, <a href="https://www.startssl.com/?app=25#52">export it from your browser as a .p12 file and import it into your mail client</a>.
+You'll need to provide a password when you export - pick a strong one, and then back up the .p12 file somewhere safe.</p>
+
+<p>
+Then, you need to convert it to a .pem file. If you have OpenSSL installed, one way is as follows:</p>
+
+<p>
+<code>openssl pkcs12 -in certificate.p12 -out certificate.pem -nodes -nokeys</code></p>
+
+<p>
+Open the .pem file in a text editor. You can recognise the public key because
+it starts "BEGIN CERTIFICATE" and ends "END CERTIFICATE" and
+has an appropriate friendly name (e.g. "StartCom Free Certificate Member's StartCom Ltd. ID").</p>
+
+<p>Paste the contents of the certificate into the SecureMail text field in [% terms.Bugzilla %].</p>
+
+<h2>PGP</h2>
+
+<b>PGP keys must be ASCII-armoured - i.e. text, with the first line containing BEGIN PGP PUBLIC KEY.</b></p>
+
+<p>
+If you already have your own PGP key in a keyring, skip straight to step 3. Otherwise:</p>
+
+<ol>
+
+<li>Install the GPG suite of utilities for your operating system, either using your package manager or downloaded from <a href="http://www.gnupg.org/download/index.en.html">gnupg.org</a>.</p>
+
+<li><p>Generate a private key.</p>
+
+<p><code>gpg --gen-key</code></p>
+
+<p>
+You’ll have to answer several questions:</p>
+
+<p>
+<ul>
+ <li>What kind and size of key you want; the defaults are probably good enough.</li>
+ <li>How long the key should be valid; you can safely choose a non-expiring key.</li>
+ <li>Your real name and e-mail address; these are necessary for identifying your key in a larger set of keys.</li>
+ <li>A comment for your key; the comment can be empty.</li>
+ <li>A passphrase. Whatever you do, don’t forget it! Your key, and all your encrypted files, will be useless if you do.</li>
+</ul>
+
+<li><p>Generate an ASCII version of your public key.</p>
+
+<p><code>gpg --armor --output pubkey.txt --export 'Your Name'</code></p>
+
+<p>Paste the contents of pubkey.txt into the SecureMail text field in [% terms.Bugzilla %].
+
+<li>Configure your email client to use your associated private key to decrypt the encrypted emails. For Thunderbird, you need the <a href="https://addons.mozilla.org/en-us/thunderbird/addon/enigmail/">Enigmail</a> extension.</p>
+</ol>
+
+<p>
+Further reading: <a href="http://www.madboa.com/geek/gpg-quickstart">GPG Quickstart</a>.
+
+[% PROCESS global/footer.html.tmpl %]
+
+
diff --git a/extensions/ShadowBugs/Config.pm b/extensions/ShadowBugs/Config.pm
new file mode 100644
index 000000000..6999edaf3
--- /dev/null
+++ b/extensions/ShadowBugs/Config.pm
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ShadowBugs;
+use strict;
+
+use constant NAME => 'ShadowBugs';
+use constant REQUIRED_MODULES => [];
+use constant OPTIONAL_MODULES => [];
+
+__PACKAGE__->NAME;
diff --git a/extensions/ShadowBugs/Extension.pm b/extensions/ShadowBugs/Extension.pm
new file mode 100644
index 000000000..a9a1e0861
--- /dev/null
+++ b/extensions/ShadowBugs/Extension.pm
@@ -0,0 +1,99 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::ShadowBugs;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Bug;
+use Bugzilla::Error;
+use Bugzilla::Field;
+use Bugzilla::User;
+
+our $VERSION = '1';
+
+BEGIN {
+ *Bugzilla::is_cf_shadow_bug_hidden = \&_is_cf_shadow_bug_hidden;
+ *Bugzilla::Bug::cf_shadow_bug_obj = \&_cf_shadow_bug_obj;
+}
+
+# Determine if the shadow-bug / shadowed-by fields are visibile on the
+# specified bug.
+sub _is_cf_shadow_bug_hidden {
+ my ($self, $bug) = @_;
+
+ # completely hide unless you're a member of the right group
+ return 1 unless Bugzilla->user->in_group('can_shadow_bugs');
+
+ my $is_public = Bugzilla::User->new()->can_see_bug($bug->id);
+ if ($is_public) {
+ # hide on public bugs, unless it's shadowed
+ my $related = $bug->related_bugs(Bugzilla->process_cache->{shadow_bug_field});
+ return 1 if !@$related;
+ }
+}
+
+sub _cf_shadow_bug_obj {
+ my ($self) = @_;
+ return unless $self->cf_shadow_bug;
+ return $self->{cf_shadow_bug_obj} ||= Bugzilla::Bug->new($self->cf_shadow_bug);
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ Bugzilla->process_cache->{shadow_bug_field} ||= Bugzilla::Field->new({ name => 'cf_shadow_bug' });
+
+ return unless Bugzilla->user->in_group('can_shadow_bugs');
+ return unless
+ $file eq 'bug/edit.html.tmpl'
+ || $file eq 'bug/show.html.tmpl'
+ || $file eq 'bug/show-header.html.tmpl';
+ my $bug = exists $vars->{'bugs'} ? $vars->{'bugs'}[0] : $vars->{'bug'};
+ return unless $bug && $bug->cf_shadow_bug;
+ $vars->{is_shadow_bug} = 1;
+
+ if ($file eq 'bug/edit.html.tmpl') {
+ # load comments from other bug
+ $vars->{shadow_comments} = $bug->cf_shadow_bug_obj->comments;
+ }
+}
+
+sub bug_end_of_update {
+ my ($self, $args) = @_;
+
+ # don't allow shadowing non-public bugs
+ if (exists $args->{changes}->{cf_shadow_bug}) {
+ my ($old_id, $new_id) = @{ $args->{changes}->{cf_shadow_bug} };
+ if ($new_id) {
+ if (!Bugzilla::User->new()->can_see_bug($new_id)) {
+ ThrowUserError('illegal_shadow_bug_public', { id => $new_id });
+ }
+ }
+ }
+
+ # if a shadow bug is made public, clear the shadow_bug field
+ if (exists $args->{changes}->{bug_group}) {
+ my $bug = $args->{bug};
+ return unless my $shadow_id = $bug->cf_shadow_bug;
+ my $is_public = Bugzilla::User->new()->can_see_bug($bug->id);
+ if ($is_public) {
+ Bugzilla->dbh->do(
+ "UPDATE bugs SET cf_shadow_bug=NULL WHERE bug_id=?",
+ undef, $bug->id);
+ LogActivityEntry($bug->id, 'cf_shadow_bug', $shadow_id, '',
+ Bugzilla->user->id, $args->{timestamp});
+
+ }
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/ShadowBugs/disabled b/extensions/ShadowBugs/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/ShadowBugs/disabled
diff --git a/extensions/ShadowBugs/template/en/default/hook/bug/comments-aftercomments.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/bug/comments-aftercomments.html.tmpl
new file mode 100644
index 000000000..d8dae521a
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/bug/comments-aftercomments.html.tmpl
@@ -0,0 +1,70 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS is_shadow_bug %]
+
+[% public_bug = bug.cf_shadow_bug_obj %]
+[% count = 0 %]
+[% FOREACH comment = shadow_comments %]
+ [% IF count >= start_at %]
+ [% PROCESS a_comment %]
+ [% END %]
+ [% count = count + increment %]
+[% END %]
+
+[% BLOCK a_comment %]
+ [% RETURN IF comment.is_private AND NOT (user.is_insider || user.id == comment.author.id) %]
+ [% comment_text = comment.body_full %]
+ [% RETURN IF comment_text == '' %]
+
+ <div id="pc[% count %]" class="bz_comment[% " bz_private" IF comment.is_private %]
+ shadow_bug_comment bz_default_hidden
+ [% " bz_first_comment" IF count == description %]">
+ [% IF count == description %]
+ [% class_name = "bz_first_comment_head" %]
+ [% comment_label = "Public Description" %]
+ [% ELSE %]
+ [% class_name = "bz_comment_head" %]
+ [% comment_label = "Public Comment " _ count %]
+ [% END %]
+
+ <div class="[% class_name FILTER html %]">
+ <span class="bz_comment_number">
+ <a href="show_bug.cgi?id=[% public_bug.bug_id FILTER none %]#c[% count %]">
+ [%- comment_label FILTER html %]</a>
+ </span>
+
+ <span class="bz_comment_user">
+ [% commenter_id = comment.author.id %]
+ [% UNLESS user_cache.$commenter_id %]
+ [% user_cache.$commenter_id = BLOCK %]
+ [% INCLUDE global/user.html.tmpl who = comment.author %]
+ [% END %]
+ [% END %]
+ [% user_cache.$commenter_id FILTER none %]
+ [% Hook.process('user', 'bug/comments.html.tmpl') %]
+ </span>
+
+ <span class="bz_comment_user_images">
+ [% FOREACH group = comment.author.groups_with_icon %]
+ <img src="[% group.icon_url FILTER html %]"
+ alt="[% group.name FILTER html %]"
+ title="[% group.name FILTER html %] - [% group.description FILTER html %]">
+ [% END %]
+ </span>
+
+ <span class="bz_comment_time">
+ [%+ comment.creation_ts FILTER time %]
+ </span>
+ </div>
+
+<pre class="bz_comment_text">
+ [%- comment_text FILTER quoteUrls(public_bug, comment) -%]
+</pre>
+ </div>
+[% END %]
diff --git a/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_comment_textarea.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_comment_textarea.html.tmpl
new file mode 100644
index 000000000..9873ea3d7
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_comment_textarea.html.tmpl
@@ -0,0 +1,13 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS is_shadow_bug %]
+
+<br>
+<a href="show_bug.cgi?id=[% bug.cf_shadow_bug FILTER none %]#comment">Add public comment</a>
+
diff --git a/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..8e8327ef2
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,27 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN IF Bugzilla.is_cf_shadow_bug_hidden(bug) %]
+[% field = Bugzilla.process_cache.shadow_bug_field %]
+[% shadowed_by = bug.related_bugs(field).pop %]
+<tr>
+ [% IF shadowed_by && user.can_see_bug(shadowed_by) %]
+ <th class="field_label">
+ [% field.reverse_desc FILTER html %]:
+ </th>
+ <td>
+ [% shadowed_by.id FILTER bug_link(shadowed_by, use_alias => 1) FILTER none %][% " " %]
+ </td>
+ [% ELSE %]
+ [% PROCESS bug/field.html.tmpl
+ value = bug.cf_shadow_bug
+ editable = bug.check_can_change_field(field.name, 0, 1)
+ no_tds = false
+ value_span = 2 %]
+ [% END %]
+</tr>
diff --git a/extensions/ShadowBugs/template/en/default/hook/bug/edit-custom_field.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/bug/edit-custom_field.html.tmpl
new file mode 100644
index 000000000..4389b27ad
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/bug/edit-custom_field.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% field.hidden = field.name == 'cf_shadow_bug' %]
diff --git a/extensions/ShadowBugs/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..5786b3df6
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,12 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF is_shadow_bug %]
+ [% style_urls.push('extensions/ShadowBugs/web/style.css') %]
+ [% javascript_urls.push('extensions/ShadowBugs/web/shadow-bugs.js') %]
+[% END %]
diff --git a/extensions/ShadowBugs/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/ShadowBugs/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..2e7695dbb
--- /dev/null
+++ b/extensions/ShadowBugs/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,14 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "illegal_shadow_bug_public" %]
+ [% title = "Invalid Shadow " _ terms.Bug %]
+ You cannot shadow [% terms.bug %] [%+ id FILTER html %] because it is not a
+ public [% terms.bug %].
+[% END %]
+
diff --git a/extensions/ShadowBugs/web/shadow-bugs.js b/extensions/ShadowBugs/web/shadow-bugs.js
new file mode 100644
index 000000000..ff320e117
--- /dev/null
+++ b/extensions/ShadowBugs/web/shadow-bugs.js
@@ -0,0 +1,51 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+var shadow_bug = {
+ init: function() {
+ var Dom = YAHOO.util.Dom;
+ var comment_divs = Dom.getElementsByClassName('bz_comment', 'div', 'comments');
+ var comments = new Array();
+ for (var i = 0, l = comment_divs.length; i < l; i++) {
+ var time_spans = Dom.getElementsByClassName('bz_comment_time', 'span', comment_divs[i]);
+ if (!time_spans.length) continue;
+ var date = this.parse_date(time_spans[0].innerHTML);
+ if (!date) continue;
+
+ var comment = {};
+ comment.div = comment_divs[i];
+ comment.date = date;
+ comment.shadow = Dom.hasClass(comment.div, 'shadow_bug_comment');
+ comments.push(comment);
+ }
+
+ for (var i = 0, l = comments.length; i < l; i++) {
+ if (!comments[i].shadow) continue;
+ for (var j = 0, jl = comments.length; j < jl; j++) {
+ if (comments[j].shadow) continue;
+ if (comments[j].date > comments[i].date) {
+ comments[j].div.parentNode.insertBefore(comments[i].div, comments[j].div);
+ break;
+ }
+ }
+ Dom.removeClass(comments[i].div, 'bz_default_hidden');
+ }
+
+ Dom.get('comment').placeholder = 'Add non-public comment';
+ },
+
+ parse_date: function(date) {
+ var matches = date.match(/^\s*(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
+ if (!matches) return;
+ return (matches[1] + matches[2] + matches[3] + matches[4] + matches[5] + matches[6]) + 0;
+ }
+};
+
+
+YAHOO.util.Event.onDOMReady(function() {
+ shadow_bug.init();
+});
diff --git a/extensions/ShadowBugs/web/style.css b/extensions/ShadowBugs/web/style.css
new file mode 100644
index 000000000..0c104130f
--- /dev/null
+++ b/extensions/ShadowBugs/web/style.css
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+.shadow_bug_comment {
+ background: transparent !important;
+}
diff --git a/extensions/SiteMapIndex/Config.pm b/extensions/SiteMapIndex/Config.pm
new file mode 100644
index 000000000..e10d6ec8b
--- /dev/null
+++ b/extensions/SiteMapIndex/Config.pm
@@ -0,0 +1,36 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Sitemap Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Everything Solved, Inc.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Max Kanat-Alexander <mkanat@bugzilla.org>
+# Dave Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::SiteMapIndex;
+use strict;
+
+use constant NAME => 'SiteMapIndex';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'IO-Compress-Gzip',
+ module => 'IO::Compress::Gzip',
+ version => 0,
+ }
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/SiteMapIndex/Extension.pm b/extensions/SiteMapIndex/Extension.pm
new file mode 100644
index 000000000..f36fa8c81
--- /dev/null
+++ b/extensions/SiteMapIndex/Extension.pm
@@ -0,0 +1,157 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Sitemap Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Everything Solved, Inc.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Max Kanat-Alexander <mkanat@bugzilla.org>
+# Dave Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::SiteMapIndex;
+use strict;
+use base qw(Bugzilla::Extension);
+
+our $VERSION = '1.0';
+
+use Bugzilla::Constants qw(bz_locations ON_WINDOWS);
+use Bugzilla::Util qw(correct_urlbase get_text);
+use Bugzilla::Install::Filesystem;
+
+use Bugzilla::Extension::SiteMapIndex::Constants;
+use Bugzilla::Extension::SiteMapIndex::Util;
+
+use DateTime;
+use IO::File;
+use POSIX;
+
+#########
+# Pages #
+#########
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my ($vars, $file) = @$args{qw(vars file)};
+
+ return if !$file eq 'global/header.html.tmpl';
+ return unless (exists $vars->{bug} or exists $vars->{bugs});
+ my $bugs = exists $vars->{bugs} ? $vars->{bugs} : [$vars->{bug}];
+ return if !ref $bugs eq 'ARRAY';
+
+ foreach my $bug (@$bugs) {
+ if (!bug_is_ok_to_index($bug)) {
+ $vars->{sitemap_noindex} = 1;
+ last;
+ }
+ }
+}
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{page_id};
+
+ if ($page =~ m{^sitemap/sitemap\.}) {
+ my $map = generate_sitemap(__PACKAGE__->NAME);
+ print Bugzilla->cgi->header('text/xml');
+ print $map;
+ exit;
+ }
+}
+
+################
+# Installation #
+################
+
+sub install_before_final_checks {
+ my ($self) = @_;
+ if (!correct_urlbase()) {
+ print STDERR get_text('sitemap_no_urlbase'), "\n";
+ return;
+ }
+ if (Bugzilla->params->{'requirelogin'}) {
+ print STDERR get_text('sitemap_requirelogin'), "\n";
+ return;
+ }
+
+ $self->_fix_robots_txt();
+}
+
+sub install_filesystem {
+ my ($self, $args) = @_;
+ my $create_dirs = $args->{'create_dirs'};
+ my $recurse_dirs = $args->{'recurse_dirs'};
+ my $htaccess = $args->{'htaccess'};
+
+ # Create the sitemap directory to store the index and sitemap files
+ my $sitemap_path = bz_locations->{'datadir'} . "/" . __PACKAGE__->NAME;
+
+ $create_dirs->{$sitemap_path} = Bugzilla::Install::Filesystem::DIR_CGI_WRITE
+ | Bugzilla::Install::Filesystem::DIR_ALSO_WS_SERVE;
+
+ $recurse_dirs->{$sitemap_path} = {
+ files => Bugzilla::Install::Filesystem::CGI_WRITE
+ | Bugzilla::Install::Filesystem::DIR_ALSO_WS_SERVE,
+ dirs => Bugzilla::Install::Filesystem::DIR_CGI_WRITE
+ | Bugzilla::Install::Filesystem::DIR_ALSO_WS_SERVE
+ };
+
+ # Create a htaccess file that allows the sitemap files to be served out
+ $htaccess->{"$sitemap_path/.htaccess"} = {
+ perms => Bugzilla::Install::Filesystem::WS_SERVE,
+ contents => <<EOT
+# Allow access to sitemap files created by the SiteMapIndex extension
+<FilesMatch ^sitemap.*\\.xml(.gz)?\$>
+ Allow from all
+</FilesMatch>
+Deny from all
+EOT
+ };
+}
+
+sub _fix_robots_txt {
+ my ($self) = @_;
+ my $cgi_path = bz_locations()->{'cgi_path'};
+ my $robots_file = "$cgi_path/robots.txt";
+ my $current_fh = new IO::File("$cgi_path/robots.txt", 'r');
+ if (!$current_fh) {
+ warn "$robots_file: $!";
+ return;
+ }
+
+ my $current_contents;
+ { local $/; $current_contents = <$current_fh> }
+ $current_fh->close();
+
+ return if $current_contents =~ m{^Allow: \/\*show_bug\.cgi}ms;
+ my $backup_name = "$cgi_path/robots.txt.old";
+ print get_text('sitemap_fixing_robots', { current => $robots_file,
+ backup => $backup_name }), "\n";
+ rename $robots_file, $backup_name or die "backup failed: $!";
+
+ my $new_fh = new IO::File($self->package_dir . '/robots.txt', 'r');
+ $new_fh || die "Could not open new robots.txt template file: $!";
+ my $new_contents;
+ { local $/; $new_contents = <$new_fh> }
+ $new_fh->close() || die "Could not close new robots.txt template file: $!";
+
+ my $sitemap_url = correct_urlbase() . SITEMAP_URL;
+ $new_contents =~ s/SITEMAP_URL/$sitemap_url/;
+ $new_fh = new IO::File("$cgi_path/robots.txt", 'w');
+ $new_fh || die "Could not open new robots.txt file: $!";
+ print $new_fh $new_contents;
+ $new_fh->close() || die "Could not close new robots.txt file: $!";
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/SiteMapIndex/lib/Constants.pm b/extensions/SiteMapIndex/lib/Constants.pm
new file mode 100644
index 000000000..fce858121
--- /dev/null
+++ b/extensions/SiteMapIndex/lib/Constants.pm
@@ -0,0 +1,47 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Sitemap Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Everything Solved, Inc.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Max Kanat-Alexander <mkanat@bugzilla.org>
+
+package Bugzilla::Extension::SiteMapIndex::Constants;
+use strict;
+use base qw(Exporter);
+our @EXPORT = qw(
+ SITEMAP_AGE
+ SITEMAP_MAX
+ SITEMAP_DELAY
+ SITEMAP_URL
+);
+
+# This is the amount of hours a sitemap index and it's files are considered
+# valid before needing to be regenerated.
+use constant SITEMAP_AGE => 12;
+
+# This is the largest number of entries that can be in a single sitemap file,
+# per the sitemaps.org standard.
+use constant SITEMAP_MAX => 50_000;
+
+# We only show bugs that are at least 12 hours old, because if somebody
+# files a bug that's a security bug but doesn't protect it, we want to give
+# them time to fix that.
+use constant SITEMAP_DELAY => 12;
+
+use constant SITEMAP_URL => 'page.cgi?id=sitemap/sitemap.xml';
+
+1;
diff --git a/extensions/SiteMapIndex/lib/Util.pm b/extensions/SiteMapIndex/lib/Util.pm
new file mode 100644
index 000000000..5c02a5989
--- /dev/null
+++ b/extensions/SiteMapIndex/lib/Util.pm
@@ -0,0 +1,205 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Sitemap Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Everything Solved, Inc.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Max Kanat-Alexander <mkanat@bugzilla.org>
+# Dave Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::SiteMapIndex::Util;
+use strict;
+use base qw(Exporter);
+our @EXPORT = qw(
+ generate_sitemap
+ bug_is_ok_to_index
+);
+
+use Bugzilla::Extension::SiteMapIndex::Constants;
+
+use Bugzilla::Util qw(correct_urlbase datetime_from url_quote);
+use Bugzilla::Constants qw(bz_locations);
+
+use Scalar::Util qw(blessed);
+use IO::Compress::Gzip qw(gzip $GzipError);
+
+sub too_young_date {
+ my $hours_ago = DateTime->now(time_zone => Bugzilla->local_timezone);
+ $hours_ago->subtract(hours => SITEMAP_DELAY);
+ return $hours_ago;
+}
+
+sub bug_is_ok_to_index {
+ my ($bug) = @_;
+ return 1 unless blessed($bug) && $bug->isa('Bugzilla::Bug') && !$bug->{error};
+ my $creation_ts = datetime_from($bug->creation_ts);
+ return ($creation_ts && $creation_ts lt too_young_date()) ? 1 : 0;
+}
+
+# We put two things in the Sitemap: a list of Browse links for products,
+# and links to bugs.
+sub generate_sitemap {
+ my ($extension_name) = @_;
+
+ # If file is less than SITEMAP_AGE hours old, then read in and send to caller.
+ # If greater, then regenerate and send the new version.
+ my $index_file = bz_locations->{'datadir'} . "/$extension_name/sitemap_index.xml";
+ if (-e $index_file) {
+ my $index_mtime = (stat($index_file))[9];
+ my $index_hours = sprintf("%d", (time() - $index_mtime) / 60 / 60); # in hours
+ if ($index_hours < SITEMAP_AGE) {
+ my $index_fh = new IO::File($index_file, 'r');
+ $index_fh || die "Could not open current sitemap index: $!";
+ my $index_xml;
+ { local $/; $index_xml = <$index_fh> }
+ $index_fh->close() || die "Could not close current sitemap index: $!";
+
+ return $index_xml;
+ }
+ }
+
+ # Set the atime and mtime of the index file to the current time
+ # in case another request is made before we finish.
+ utime(undef, undef, $index_file);
+
+ # Sitemaps must never contain private data.
+ Bugzilla->logout_request();
+ my $user = Bugzilla->user;
+ my $products = $user->get_accessible_products;
+
+ my $num_bugs = SITEMAP_MAX - scalar(@$products);
+ # We do this date math outside of the database because databases
+ # usually do better with a straight comparison value.
+ my $hours_ago = too_young_date();
+
+ # We don't use Bugzilla::Bug objects, because this could be a tremendous
+ # amount of data, and we only want a little. Also, we only display
+ # bugs that are not in any group. We show the last $num_bugs
+ # most-recently-updated bugs.
+ my $dbh = Bugzilla->dbh;
+ my $bug_sth = $dbh->prepare(
+ 'SELECT bugs.bug_id, bugs.delta_ts
+ FROM bugs
+ LEFT JOIN bug_group_map ON bugs.bug_id = bug_group_map.bug_id
+ WHERE bug_group_map.bug_id IS NULL AND creation_ts < ?
+ ' . $dbh->sql_limit($num_bugs, '?'));
+
+ my $filecount = 1;
+ my $filelist = [];
+ my $offset = 0;
+
+ while (1) {
+ my $bugs = [];
+
+ $bug_sth->execute($hours_ago, $offset);
+
+ while (my ($bug_id, $delta_ts) = $bug_sth->fetchrow_array()) {
+ push(@$bugs, { bug_id => $bug_id, delta_ts => $delta_ts });
+ }
+
+ last if !@$bugs;
+
+ # We only need the product links in the first sitemap file
+ $products = [] if $filecount > 1;
+
+ push(@$filelist, _generate_sitemap_file($extension_name, $filecount, $products, $bugs));
+
+ $filecount++;
+ $offset += $num_bugs;
+ }
+
+ # Generate index file
+ return _generate_sitemap_index($extension_name, $filelist);
+}
+
+sub _generate_sitemap_index {
+ my ($extension_name, $filelist) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ my $timestamp = $dbh->selectrow_array(
+ "SELECT " . $dbh->sql_date_format('NOW()', '%Y-%m-%d'));
+
+ my $index_xml = <<END;
+<?xml version="1.0" encoding="UTF-8"?>
+<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+END
+
+ foreach my $filename (@$filelist) {
+ $index_xml .= "
+ <sitemap>
+ <loc>" . correct_urlbase() . "data/$extension_name/$filename</loc>
+ <lastmod>$timestamp</lastmod>
+ </sitemap>
+";
+ }
+
+ $index_xml .= <<END;
+</sitemapindex>
+END
+
+ my $index_file = bz_locations->{'datadir'} . "/$extension_name/sitemap_index.xml";
+ my $index_fh = new IO::File($index_file, 'w');
+ $index_fh || die "Could not open new sitemap index: $!";
+ print $index_fh $index_xml;
+ $index_fh->close() || die "Could not close new sitemap index: $!";
+
+ return $index_xml;
+}
+
+sub _generate_sitemap_file {
+ my ($extension_name, $filecount, $products, $bugs) = @_;
+
+ my $bug_url = correct_urlbase() . 'show_bug.cgi?id=';
+ my $product_url = correct_urlbase() . 'describecomponents.cgi?product=';
+
+ my $sitemap_xml = <<END;
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+END
+
+ foreach my $product (@$products) {
+ $sitemap_xml .= "
+ <url>
+ <loc>" . $product_url . url_quote($product->name) . "</loc>
+ <changefreq>daily</changefreq>
+ <priority>0.4</priority>
+ </url>
+";
+ }
+
+ foreach my $bug (@$bugs) {
+ $sitemap_xml .= "
+ <url>
+ <loc>" . $bug_url . $bug->{bug_id} . "</loc>
+ <lastmod>" . datetime_from($bug->{delta_ts}, 'UTC')->iso8601 . 'Z' . "</lastmod>
+ </url>
+";
+ }
+
+ $sitemap_xml .= <<END;
+</urlset>
+END
+
+ # Write the compressed sitemap data to a file in the cgi root so that they can
+ # be accessed by the search engines.
+ my $filename = "sitemap$filecount.xml.gz";
+ gzip \$sitemap_xml => bz_locations->{'datadir'} . "/$extension_name/$filename"
+ || die "gzip failed: $GzipError\n";
+
+ return $filename;
+}
+
+1;
diff --git a/extensions/SiteMapIndex/robots.txt b/extensions/SiteMapIndex/robots.txt
new file mode 100644
index 000000000..7adeebd32
--- /dev/null
+++ b/extensions/SiteMapIndex/robots.txt
@@ -0,0 +1,10 @@
+User-agent: *
+Disallow: /*.cgi
+Disallow: /*show_bug.cgi*ctype=*
+Allow: /
+Allow: /*index.cgi
+Allow: /*page.cgi
+Allow: /*show_bug.cgi
+Allow: /*describecomponents.cgi
+Allow: /*data/SiteMapIndex/sitemap*.xml.gz
+Sitemap: SITEMAP_URL
diff --git a/extensions/SiteMapIndex/template/en/default/hook/global/header-additional_header.html.tmpl b/extensions/SiteMapIndex/template/en/default/hook/global/header-additional_header.html.tmpl
new file mode 100644
index 000000000..682f6093f
--- /dev/null
+++ b/extensions/SiteMapIndex/template/en/default/hook/global/header-additional_header.html.tmpl
@@ -0,0 +1,23 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Initial Developer of the Original Code is Everything Solved, Inc.
+ # Portions created by Everything Solved are Copyright (C) 2010
+ # Everything Solved. All Rights Reserved.
+ #
+ # The Original Code is the Bugzilla Sitemap Extension.
+ #
+ # Contributor(s):
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+
+[% SET meta_robots = ['noarchive'] %]
+[% meta_robots.push('noindex') IF sitemap_noindex %]
+<meta name="robots" content="[% meta_robots.join(',') FILTER html %]">
diff --git a/extensions/SiteMapIndex/template/en/default/hook/global/messages-messages.html.tmpl b/extensions/SiteMapIndex/template/en/default/hook/global/messages-messages.html.tmpl
new file mode 100644
index 000000000..0d0e9fd74
--- /dev/null
+++ b/extensions/SiteMapIndex/template/en/default/hook/global/messages-messages.html.tmpl
@@ -0,0 +1,37 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Initial Developer of the Original Code is Everything Solved, Inc.
+ # Portions created by Everything Solved are Copyright (C) 2010
+ # Everything Solved. All Rights Reserved.
+ #
+ # The Original Code is the Bugzilla Sitemap Extension.
+ #
+ # Contributor(s):
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ #%]
+
+[% IF message_tag == "sitemap_fixing_robots" %]
+ Replacing [% current FILTER html %]. (The old version will be saved
+ as "[% backup FILTER html %]". You can delete the old version if you
+ do not need its contents.)
+
+[% ELSIF message_tag == "sitemap_requirelogin" %]
+ Not updating search engines with your sitemap, because you have the
+ "requirelogin" parameter turned on, and so search engines will not be
+ able to access your sitemap.
+
+[% ELSIF message_tag == "sitemap_no_urlbase" %]
+ You have not yet set the "urlbase" parameter. We cannot update
+ search engines and inform them about your sitemap without a
+ urlbase. Please set the "urlbase" parameter and re-run
+ checksetup.pl.
+
+[% END %]
diff --git a/extensions/Splinter/Config.pm b/extensions/Splinter/Config.pm
new file mode 100644
index 000000000..d36a28922
--- /dev/null
+++ b/extensions/Splinter/Config.pm
@@ -0,0 +1,5 @@
+package Bugzilla::Extension::Splinter;
+use strict;
+use constant NAME => 'Splinter';
+
+__PACKAGE__->NAME;
diff --git a/extensions/Splinter/Extension.pm b/extensions/Splinter/Extension.pm
new file mode 100644
index 000000000..ecf61ea9a
--- /dev/null
+++ b/extensions/Splinter/Extension.pm
@@ -0,0 +1,146 @@
+package Bugzilla::Extension::Splinter;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla;
+use Bugzilla::Bug;
+use Bugzilla::Template;
+use Bugzilla::Attachment;
+use Bugzilla::BugMail;
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Field;
+use Bugzilla::Util qw(trim detaint_natural);
+
+use Bugzilla::Extension::Splinter::Util;
+
+our $VERSION = '0.1';
+
+BEGIN {
+ *Bugzilla::splinter_review_base = \&get_review_base;
+ *Bugzilla::splinter_review_url = \&_get_review_url;
+}
+
+sub _get_review_url {
+ my ($class, $bug_id, $attach_id) = @_;
+ return get_review_url(Bugzilla::Bug->check({ id => $bug_id, cache => 1 }), $attach_id);
+}
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my ($vars, $page) = @$args{qw(vars page_id)};
+
+ if ($page eq 'splinter.html') {
+ # Login is required for performing a review
+ my $user = Bugzilla->login(LOGIN_REQUIRED);
+
+ # We can either provide just a bug id to see a list
+ # of prior reviews by the user, or just an attachment
+ # id to go directly to a review page for the attachment.
+ # If both are give they will be checked later to make
+ # sure they are connected.
+
+ my $input = Bugzilla->input_params;
+ if ($input->{'bug'}) {
+ $vars->{'bug_id'} = $input->{'bug'};
+ $vars->{'attach_id'} = $input->{'attachment'};
+ $vars->{'bug'} = Bugzilla::Bug->check({ id => $input->{'bug'}, cache => 1 });
+ }
+
+ if ($input->{'attachment'}) {
+ my $attachment = Bugzilla::Attachment->check({ id => $input->{'attachment'} });
+
+ # Check to see if the user can see the bug this attachment is connected to.
+ Bugzilla::Bug->check($attachment->bug_id);
+ if ($attachment->isprivate && $user->id != $attachment->attacher->id
+ && !$user->is_insider)
+ {
+ ThrowUserError('auth_failure', {action => 'access',
+ object => 'attachment'});
+ }
+
+ # If the user provided both a bug id and an attachment id, they must
+ # be connected to each other
+ if ($input->{'bug'} && $input->{'bug'} != $attachment->bug_id) {
+ ThrowUserError('bug_attach_id_mismatch');
+ }
+
+ # The patch is going to be displayed in a HTML page and if the utf8
+ # param is enabled, we have to encode attachment data as utf8.
+ if (Bugzilla->params->{'utf8'}) {
+ $attachment->data; # load data
+ utf8::decode($attachment->{data});
+ }
+
+ $vars->{'attach_id'} = $attachment->id;
+ $vars->{'attach_data'} = $attachment->data;
+ }
+
+ my $field_object = new Bugzilla::Field({ name => 'attachments.status' });
+ my $statuses;
+ if ($field_object) {
+ $statuses = [map { $_->name } @{ $field_object->legal_values }];
+ } else {
+ $statuses = [];
+ }
+ $vars->{'attachment_statuses'} = $statuses;
+ }
+}
+
+
+sub bug_format_comment {
+ my ($self, $args) = @_;
+
+ my $bug = $args->{'bug'};
+ my $regexes = $args->{'regexes'};
+ my $text = $args->{'text'};
+
+ # Add [review] link to the end of "Created attachment" comments
+ #
+ # We need to work around the way that the hook works, which is intended
+ # to avoid overlapping matches, since we *want* an overlapping match
+ # here (the normal handling of "Created attachment"), so we add in
+ # dummy text and then replace in the regular expression we return from
+ # the hook.
+ $$text =~ s~((?:^Created\ |\b)attachment\s*\#?\s*(\d+)(\s\[details\])?)
+ ~(push(@$regexes, { match => qr/__REVIEW__$2/,
+ replace => get_review_link("$2", "[review]") })) &&
+ (attachment_id_is_patch($2) ? "$1 __REVIEW__$2" : $1)
+ ~egmx;
+
+ # And linkify "Review of attachment", this is less of a workaround since
+ # there is no issue with overlap; note that there is an assumption that
+ # there is only one match in the text we are linkifying, since they all
+ # get the same link.
+ my $REVIEW_RE = qr/Review\s+of\s+attachment\s+(\d+)\s*:/;
+
+ if ($$text =~ $REVIEW_RE) {
+ my $review_link = get_review_link($bug, $1, "Review");
+ my $attach_link = Bugzilla::Template::get_attachment_link($1, "attachment $1");
+
+ push(@$regexes, { match => $REVIEW_RE,
+ replace => "$review_link of $attach_link:"});
+ }
+}
+
+sub config_add_panels {
+ my ($self, $args) = @_;
+
+ my $modules = $args->{panel_modules};
+ $modules->{Splinter} = "Bugzilla::Extension::Splinter::Config";
+}
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+
+ # Post-process bug mail to add review links to bug mail.
+ # It would be nice to be able to hook in earlier in the
+ # process when the email body is being formatted in the
+ # style of the bug-format_comment link for HTML but this
+ # is the only hook available as of Bugzilla-3.4.
+ add_review_links_to_email($args->{'email'});
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Splinter/lib/Config.pm b/extensions/Splinter/lib/Config.pm
new file mode 100644
index 000000000..95b9f5dfa
--- /dev/null
+++ b/extensions/Splinter/lib/Config.pm
@@ -0,0 +1,46 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Example Plugin.
+#
+# The Initial Developer of the Original Code is Canonical Ltd.
+# Portions created by Canonical Ltd. are Copyright (C) 2008
+# Canonical Ltd. All Rights Reserved.
+#
+# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# Bradley Baetz <bbaetz@acm.org>
+# Owen Taylor <otaylor@redhat.com>
+
+package Bugzilla::Extension::Splinter::Config;
+
+use strict;
+use warnings;
+
+use Bugzilla::Config::Common;
+
+our $sortkey = 1350;
+
+sub get_param_list {
+ my ($class) = @_;
+
+ my @param_list = (
+ {
+ name => 'splinter_base',
+ type => 't',
+ default => 'page.cgi?id=splinter.html',
+ },
+ );
+
+ return @param_list;
+}
+
+1;
diff --git a/extensions/Splinter/lib/Util.pm b/extensions/Splinter/lib/Util.pm
new file mode 100644
index 000000000..5258334a7
--- /dev/null
+++ b/extensions/Splinter/lib/Util.pm
@@ -0,0 +1,160 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Splinter Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Red Hat, Inc.
+# Portions created by Red Hat, Inc. are Copyright (C) 2009
+# Red Hat Inc. All Rights Reserved.
+#
+# Contributor(s):
+# Owen Taylor <otaylor@fishsoup.net>
+
+package Bugzilla::Extension::Splinter::Util;
+
+use strict;
+
+use Bugzilla;
+use Bugzilla::Util;
+
+use base qw(Exporter);
+
+@Bugzilla::Extension::Splinter::Util::EXPORT = qw(
+ attachment_is_visible
+ attachment_id_is_patch
+ get_review_base
+ get_review_url
+ get_review_link
+ add_review_links_to_email
+);
+
+# Validates an attachment ID.
+# Takes a parameter containing the ID to be validated.
+# If the second parameter is true, the attachment ID will be validated,
+# however the current user's access to the attachment will not be checked.
+# Will return false if 1) attachment ID is not a valid number,
+# 2) attachment does not exist, or 3) user isn't allowed to access the
+# attachment.
+#
+# Returns an attachment object.
+# Based on code from attachment.cgi
+sub attachment_id_is_valid {
+ my ($attach_id, $dont_validate_access) = @_;
+
+ # Validate the specified attachment id.
+ detaint_natural($attach_id) || return 0;
+
+ # Make sure the attachment exists in the database.
+ my $attachment = new Bugzilla::Attachment({ id => $attach_id, cache => 1 })
+ || return 0;
+
+ return $attachment
+ if ($dont_validate_access || attachment_is_visible($attachment));
+}
+
+# Checks if the current user can see an attachment
+# Based on code from attachment.cgi
+sub attachment_is_visible {
+ my $attachment = shift;
+
+ $attachment->isa('Bugzilla::Attachment') || return 0;
+
+ return (Bugzilla->user->can_see_bug($attachment->bug->id)
+ && (!$attachment->isprivate
+ || Bugzilla->user->id == $attachment->attacher->id
+ || Bugzilla->user->is_insider));
+}
+
+sub attachment_id_is_patch {
+ my $attach_id = shift;
+ my $attachment = attachment_id_is_valid($attach_id);
+
+ return ($attachment && $attachment->ispatch);
+}
+
+sub get_review_base {
+ my $base = Bugzilla->params->{'splinter_base'};
+ $base =~ s!/$!!;
+ my $urlbase = correct_urlbase();
+ $urlbase =~ s!/$!! if $base =~ "^/";
+ $base = $urlbase . $base;
+ return $base;
+}
+
+sub get_review_url {
+ my ($bug, $attach_id) = @_;
+ my $base = get_review_base();
+ my $bug_id = $bug->id;
+ return $base . ($base =~ /\?/ ? '&' : '?') . "bug=$bug_id&attachment=$attach_id";
+}
+
+sub get_review_link {
+ my ($attach_id, $link_text) = @_;
+
+ my $attachment = attachment_id_is_valid($attach_id);
+
+ if ($attachment && $attachment->ispatch) {
+ return "<a href='" . html_quote(get_review_url($attachment->bug, $attach_id)) .
+ "'>$link_text</a>";
+ }
+}
+
+sub munge_create_attachment {
+ my ($bug, $intro_text, $attach_id, $view_link) = @_;
+
+ if (attachment_id_is_patch($attach_id)) {
+ return ("$intro_text" .
+ " View: $view_link\015\012" .
+ " Review: " . get_review_url($bug, $attach_id, 1) . "\015\012");
+ }
+ else {
+ return ("$intro_text --> ($view_link)");
+ }
+}
+
+# This adds review links into a bug mail before we send it out.
+# Since this is happening after newlines have been converted into
+# RFC-2822 style \r\n, we need handle line ends carefully.
+# (\015 and \012 are used because Perl \n is platform-dependent)
+sub add_review_links_to_email {
+ my $email = shift;
+ my $body = $email->body;
+ my $new_body = 0;
+ my $bug;
+
+ if ($email->header('Subject') =~ /^\[Bug\s+(\d+)\]/
+ && Bugzilla->user->can_see_bug($1))
+ {
+ $bug = Bugzilla::Bug->new({ id => $1, cache => 1 });
+ }
+
+ return unless defined $bug;
+
+ if ($body =~ /Review\s+of\s+attachment\s+\d+\s*:/) {
+ $body =~ s~(Review\s+of\s+attachment\s+(\d+)\s*:)
+ ~"$1\015\012 --> (" . get_review_url($bug, $2, 1) . ")"
+ ~egx;
+ $new_body = 1;
+ }
+
+ if ($body =~ /Created attachment \d+\015\012 --> /) {
+ $body =~ s~(Created\ attachment\ (\d+)\015\012)
+ \ -->\ \(([^\015\012]*)\)[^\015\012]*
+ ~munge_create_attachment($bug, $1, $2, $3)
+ ~egx;
+ $new_body = 1;
+ }
+
+ $email->body_set($body) if $new_body;
+}
+
+1;
diff --git a/extensions/Splinter/template/en/default/admin/params/splinter.html.tmpl b/extensions/Splinter/template/en/default/admin/params/splinter.html.tmpl
new file mode 100644
index 000000000..b28a4bd37
--- /dev/null
+++ b/extensions/Splinter/template/en/default/admin/params/splinter.html.tmpl
@@ -0,0 +1,38 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Example Plugin.
+ #
+ # The Initial Developer of the Original Code is Canonical Ltd.
+ # Portions created by Canonical Ltd. are Copyright (C) 2008
+ # Canonical Ltd. All Rights Reserved.
+ #
+ # Contributor(s): Bradley Baetz <bbaetz@acm.org>
+ # Owen Taylor <otaylor@redhat.com>
+ #%]
+[%
+ title = "Splinter Patch Review"
+ desc = "Configure Splinter"
+%]
+
+[% param_descs = {
+ splinter_base => "This is the base URL for the Splinter patch review page; " _
+ "the default value '/page.cgi?id=splinter.html' works without " _
+ "further configuration, however you may want to internally forward " _
+ "/review to that URL in your web server's configuration and then change " _
+ "this parameter. For example, with the Apache HTTP server, you can add " _
+ "the following lines to the .htaccess for Bugzilla: " _
+ "<pre>" _
+ "RewriteEngine On\n" _
+ "RewriteRule ^review(.*) page.cgi?id=splinter.html\$1 [QSA]" _
+ "</pre>"
+ }
+%]
diff --git a/extensions/Splinter/template/en/default/hook/attachment/edit-action.html.tmpl b/extensions/Splinter/template/en/default/hook/attachment/edit-action.html.tmpl
new file mode 100644
index 000000000..7648e1d76
--- /dev/null
+++ b/extensions/Splinter/template/en/default/hook/attachment/edit-action.html.tmpl
@@ -0,0 +1,25 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Splinter Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Red Hat, Inc.
+ # Portions created by Red Hat, Inc. are Copyright (C) 2008
+ # Red Hat, Inc. All Rights Reserved.
+ #
+ # Contributor(s): Owen Taylor <otaylor@redhat.com>
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% IF attachment.ispatch %]
+ &#x0020; |
+ <a href="[% Bugzilla.splinter_review_url(attachment.bug_id, attachment.id) FILTER none %]">Review</a>
+[% END %]
diff --git a/extensions/Splinter/template/en/default/hook/attachment/list-action.html.tmpl b/extensions/Splinter/template/en/default/hook/attachment/list-action.html.tmpl
new file mode 100644
index 000000000..ee793b192
--- /dev/null
+++ b/extensions/Splinter/template/en/default/hook/attachment/list-action.html.tmpl
@@ -0,0 +1,25 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Splinter Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Red Hat, Inc.
+ # Portions created by Red Hat, Inc. are Copyright (C) 2008
+ # Red Hat, Inc. All Rights Reserved.
+ #
+ # Contributor(s): Owen Taylor <otaylor@redhat.com>
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% IF attachment.ispatch %]
+ &#x0020; |
+ <a href="[% Bugzilla.splinter_review_url(bugid, attachment.id) FILTER none %]">Review</a>
+[% END %]
diff --git a/extensions/Splinter/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/Splinter/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..17ef5c08f
--- /dev/null
+++ b/extensions/Splinter/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,5 @@
+[% IF error == "bug_attach_id_mismatch" %]
+ [% title = "Bug ID and Attachment ID Mismatch" %]
+ The [% terms.bug %] id and attachment id you provided
+ are not connected to each other.
+[% END %]
diff --git a/extensions/Splinter/template/en/default/hook/request/email-after_summary.txt.tmpl b/extensions/Splinter/template/en/default/hook/request/email-after_summary.txt.tmpl
new file mode 100644
index 000000000..3a02c843a
--- /dev/null
+++ b/extensions/Splinter/template/en/default/hook/request/email-after_summary.txt.tmpl
@@ -0,0 +1,7 @@
+[% USE Bugzilla %]
+[% IF flag && flag.status == '?' && flag.type.name == 'review' && attachment && attachment.ispatch %]
+
+Review
+[%+ Bugzilla.splinter_review_url(bug.bug_id, attachment.id) FILTER none %]
+[%- END %]
+
diff --git a/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl b/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl
new file mode 100644
index 000000000..a5fc61cea
--- /dev/null
+++ b/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl
@@ -0,0 +1,4 @@
+[% IF column == 'attachment' && request.ispatch %]
+ &nbsp;
+ <a href="[% Bugzilla.splinter_review_url(request.bug_id, request.attach_id) FILTER none %]">[review]</a>
+[% END %]
diff --git a/extensions/Splinter/template/en/default/pages/splinter.html.tmpl b/extensions/Splinter/template/en/default/pages/splinter.html.tmpl
new file mode 100644
index 000000000..fc4748548
--- /dev/null
+++ b/extensions/Splinter/template/en/default/pages/splinter.html.tmpl
@@ -0,0 +1,270 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Splinter Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Red Hat, Inc.
+ # Portions created by Red Hat, Inc. are Copyright (C) 2008
+ # Red Hat, Inc. All Rights Reserved.
+ #
+ # Contributor(s): Owen Taylor <otaylor@redhat.com>
+ #%]
+
+[% bodyclasses = [] %]
+[% FOREACH group = bug.groups_in %]
+ [% bodyclasses.push("bz_group_$group.name") %]
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Patch Review"
+ header = "Patch Review"
+ style_urls = [ "js/yui/assets/skins/sam/container.css",
+ "js/yui/assets/skins/sam/button.css",
+ "js/yui/assets/skins/sam/datatable.css",
+ "extensions/Splinter/web/splinter.css",
+ "skins/custom/bug_groups.css" ]
+ javascript_urls = [ "js/yui/element/element-min.js",
+ "js/yui/container/container-min.js",
+ "js/yui/button/button-min.js",
+ "js/yui/json/json-min.js",
+ "js/yui/datasource/datasource-min.js",
+ "js/yui/datatable/datatable-min.js",
+ "extensions/Splinter/web/splinter.js" ]
+ bodyclasses = bodyclasses
+%]
+
+[% can_edit = 0 %]
+
+<script type="text/javascript">
+ Splinter.configBase = '[% Bugzilla.splinter_review_base FILTER js %]';
+ Splinter.configBugUrl = '[% urlbase FILTER js %]';
+ Splinter.configHaveExtension = true;
+ Splinter.configHelp = '[% urlbase FILTER js %]page.cgi?id=splinter/help.html';
+ Splinter.configNote = '';
+
+ Splinter.configAttachmentStatuses = [
+ [% FOREACH status = attachment_statuses %]
+ '[% status FILTER js %]',
+ [% END %]
+ ];
+
+ Splinter.bugId = Splinter.Utils.isDigits('[% bug_id FILTER js %]') ? parseInt('[% bug_id FILTER js %]') : NaN;
+ Splinter.attachmentId = Splinter.Utils.isDigits('[% attach_id FILTER html %]') ? parseInt('[% attach_id FILTER js %]') : NaN;
+
+ if (!isNaN(Splinter.bugId)) {
+ var theBug = new Splinter.Bug.Bug();
+ theBug.id = parseInt('[% bug.id FILTER js %]');
+ theBug.token = '[% update_token FILTER js %]';
+ theBug.shortDesc = Splinter.Utils.strip('[% bug.short_desc FILTER js %]');
+ theBug.creationDate = Splinter.Bug.parseDate('[% bug.creation_ts FILTER time("%Y-%m-%d %T %z") FILTER js %]');
+ theBug.reporterEmail = Splinter.Utils.strip('[% bug.reporter.email FILTER js %]');
+ theBug.reporterName = Splinter.Utils.strip('[% bug.reporter.name FILTER js %]');
+
+ [% FOREACH comment = bug.comments %]
+ [% NEXT IF comment.is_private && !user.is_insider %]
+ [% NEXT UNLESS comment.thetext.match('(?i)^\s*review\s+of\s+attachment\s+\d+\s*:') %]
+ var comment = new Splinter.Bug.Comment();
+ comment.whoName = Splinter.Utils.strip('[% comment.author.name FILTER js %]');
+ comment.whoEmail = Splinter.Utils.strip('[% comment.author.email FILTER js %]');
+ comment.date = Splinter.Bug.parseDate('[% comment.creation_ts FILTER time("%Y-%m-%d %T %z") FILTER js %]');
+ comment.text = '[% comment.thetext FILTER js %]';
+ theBug.comments.push(comment);
+ [% END %]
+
+ [% FOREACH attachment = bug.attachments %]
+ [% NEXT IF attachment.isprivate && !user.is_insider && attachment.attacher.id != user.id %]
+ [% NEXT IF !attachment.ispatch %]
+ var attachid = parseInt('[% attachment.id FILTER js %]');
+ var attachment = new Splinter.Bug.Attachment('', attachid);
+ [% IF attachment.id == attach_id && attachment.ispatch %]
+ [% flag_types = attachment.flag_types %]
+ [% can_edit = attachment.validate_can_edit %]
+ attachment.data = '[% attach_data FILTER js %]';
+ attachment.token = '[% issue_hash_token([attachment.id, attachment.modification_time]) FILTER js %]';
+ [% END %]
+ attachment.description = Splinter.Utils.strip('[% attachment.description FILTER js %]');
+ attachment.filename = Splinter.Utils.strip('[% attachment.filename FILTER js %]');
+ attachment.contenttypeentry = Splinter.Utils.strip('[% attachment.contenttypeentry FILTER js %]');
+ attachment.date = Splinter.Bug.parseDate('[% attachment.attached FILTER time("%Y-%m-%d %T %z") FILTER js %]');
+ attachment.whoName = Splinter.Utils.strip('[% attachment.attacher.name FILTER js %]');
+ attachment.whoEmail = Splinter.Utils.strip('[% attachment.attacher.email FILTER js %]');
+ attachment.isPatch = [% attachment.ispatch ? 1 : 0 %];
+ attachment.isObsolete = [% attachment.isobsolete ? 1 : 0 %];
+ attachment.isPrivate = [% attachment.isprivate ? 1 : 0 %];
+ theBug.attachments.push(attachment);
+ [% END %]
+
+ Splinter.theBug = theBug;
+ }
+</script>
+
+<!--[if lt IE 7]>
+<p style="border: 1px solid #880000; padding: 1em; background: #ffee88; font-size: 120%;">
+ Splinter Patch Review requires a modern browser, such as
+ <a href="http://www.firefox.com">Firefox</a>, for correct operation.
+</p>
+<![endif]-->
+
+<div id="helpful-links">
+ <a id="allReviewsLink" href="[% Bugzilla.splinter_review_base FILTER none %]">
+ [reviews]</a>
+ <a id='helpLink' target='splinterHelp'
+ href="[% urlbase FILTER none %]page.cgi?id=splinter/help.html">
+ [help]</a>
+</div>
+
+<div id="bugInfo" style="display: none;">
+ <b>[% terms.Bug %] <a id="bugLink"><span id="bugId"></span></a>:</b>
+ <span id="bugShortDesc"></span> -
+ <span id="bugReporter"></span> -
+ <span id="bugCreationDate"></span>
+</div>
+
+<div id="attachInfo" style="display:none;">
+ <span id="attachObsolete"></span>
+ <b>Attachment <a id="attachLink"><span id="attachId"></span></a>:</b>
+ <span id="attachDesc"></span> -
+ <span id="attachCreator"></span> -
+ <span id="attachDate"></span>
+ [% IF feature_enabled('patch_viewer') %]
+ <a href="[% urlbase FILTER none %]attachment.cgi?id=[% attach_id FILTER uri %]&amp;action=diff"
+ target="_blank">[diff]</a>
+ [% END %]
+ <a href="[% urlbase FILTER none %]attachment.cgi?id=[% attach_id FILTER uri %]&amp;action=edit"
+ target="_blank">[details]</a>
+</div>
+
+<div id="error" style="display: none;"> </div>
+
+<div id="enterBug" style="display: none;">
+ [% terms.Bug %] to review:
+ <input id="enterBugInput" />
+ <input id="enterBugGo" type="button" value="Go" />
+ <div id="chooseReview" style="display: none;">
+ Drafts and published reviews:
+ <div id="chooseReviewTable"></div>
+ </div>
+</div>
+
+<div id="chooseAttachment" style="display: none;">
+ <div id="chooseAttachmentTable"></div>
+</div>
+
+<div id="quickHelpShow" style="display:none;">
+ <p>
+ <a href="javascript:Splinter.quickHelpToggle();" title="Show the quick help section" id="quickHelpToggle">
+ Show Quick Help</a>
+ </p>
+</div>
+
+<div id="quickHelpContent" style="display:none;">
+ <p>
+ <a href="javascript:Splinter.quickHelpToggle();" title="Hide the quick help section" id="quickHelpToggle">Close Quick Help</a>
+ </p>
+ <ul id="quickHelpList">
+ <li>From the Overview page, you can add a more generic overview comment that will appear at the beginning of your review.</li>
+ <li>To comment on a specific lines in the patch, first select the filename from the file navigation links.</li>
+ <li>Then double click the line you want to review and a comment box will appear below the line.</li>
+ <li>When the review is complete and you publish it, the overview comment and all line specific comments with their context,
+ will be combined together into a single review comment on the [% terms.bug %] report.</li>
+ <li>For more detailed instructions, read the Splinter
+ <a id='helpLink' target='splinterHelp' href="[% urlbase FILTER none %]page.cgi?id=splinter/help.html">help page</a>.
+ </li>
+ </ul>
+</div>
+
+<div id="navigationContainer" style="display: none;">
+ <b>Navigation:</b> <span id="navigation"></span>
+</div>
+
+<div id="overview" style="display: none;">
+ <div id="patchIntro"></div>
+ <div>
+ <span id="restored" style="display: none;">
+ (Restored from draft; last edited <span id="restoredLastModified"></span>)
+ </span>
+ </div>
+ <div>
+ <div id="myCommentFrame">
+ <textarea id="myComment"></textarea>
+ <div id="emptyCommentNotice">&lt;Overall Comment&gt;</div>
+ </div>
+ <div id="myPatchComments"></div>
+ <form id="publish" method="post" action="attachment.cgi" onsubmit="normalizeComments();">
+ <input type="hidden" id="publish_token" name="token" value="">
+ <input type="hidden" id="publish_action" name="action" value="update">
+ <input type="hidden" id="publish_review" name="comment" value="">
+ <input type="hidden" id="publish_attach_id" name="id" value="">
+ <input type="hidden" id="publish_attach_desc" name="description" value="">
+ <input type="hidden" id="publish_attach_filename" name="filename" value="">
+ <input type="hidden" id="publish_attach_contenttype" name="contenttypeentry" value="">
+ <input type="hidden" id="publish_attach_ispatch" name="ispatch" value="">
+ <input type="hidden" id="publish_attach_isobsolete" name="isobsolete" value="">
+ <input type="hidden" id="publish_attach_isprivate" name="isprivate" value="">
+ <div id="attachment_flags">
+ [% any_flags_requesteeble = 0 %]
+ [% FOREACH flag_type = flag_types %]
+ [% NEXT UNLESS flag_type.is_active %]
+ [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %]
+ [% END %]
+ [% IF flag_types.size > 0 %]
+ [% PROCESS "flag/list.html.tmpl" bug_id = bug_id
+ attach_id = attach_d
+ flag_types = flag_types
+ read_only_flags = !can_edit
+ any_flags_requesteeble = any_flags_requesteeble
+ %]
+ [% END %]
+ <script>
+ [% FOREACH flag_type = flag_types %]
+ [% NEXT UNLESS flag_type.is_active %]
+ Event.addListener('flag_type-[% flag_type.id FILTER js %]', 'change',
+ function() { Splinter.flagChanged = 1;
+ Splinter.queueUpdateHaveDraft(); });
+ [% FOREACH flag = flag_type.flags %]
+ Event.addListener('flag-[% flag.id FILTER js %]', 'change',
+ function() { Splinter.flagChanged = 1;
+ Splinter.queueUpdateHaveDraft(); });
+ [% END %]
+ [% END %]
+ </script>
+ </div>
+ </form>
+ <div id="buttonBox">
+ <span id="attachmentStatusSpan">Patch Status:
+ <select id="attachmentStatus"> </select>
+ </span>
+ <input id="publishButton" type="button" value="Publish" />
+ <input id="cancelButton" type="button" value="Cancel" />
+ </div>
+ <div class="clear"></div>
+ </div>
+ <div id="oldReviews" style="display: none;">
+ <div class="review-title">
+ Previous Reviews
+ </div>
+ </div>
+</div>
+
+<div id="files" style="display: none;">
+ <div id="file-collapse-all" style="display:none;">
+ <a href="javascript:void(0);" onclick="Splinter.toggleCollapsed('', 'none')">Collapse All</a> |
+ <a href="javascript:void(0);" onclick="Splinter.toggleCollapsed('', 'block')">Expand All</a>
+ </div>
+</div>
+
+<div id="credits">
+ Powered by <a href="http://fishsoup.net/software/splinter">Splinter</a>
+</div>
+
+<div id="saveDraftNotice" style="display: none;"></div>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/Splinter/template/en/default/pages/splinter/help.html.tmpl b/extensions/Splinter/template/en/default/pages/splinter/help.html.tmpl
new file mode 100644
index 000000000..dac513e56
--- /dev/null
+++ b/extensions/Splinter/template/en/default/pages/splinter/help.html.tmpl
@@ -0,0 +1,153 @@
+[%#
+ # The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Splinter Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Red Hat, Inc.
+ # Portions created by Red Hat, Inc. are Copyright (C) 2008
+ # Red Hat, Inc. All Rights Reserved.
+ #
+ # Contributor(s): Owen Taylor <otaylor@redhat.com>
+ #%]
+
+[% PROCESS global/header.html.tmpl
+ title = "Patch Review Help"
+ header = "Patch Review Help"
+%]
+
+<h2>Splinter Patch Review</h2>
+<p>
+ Splinter is an add-on for [% terms.Bugzilla %] to allow conveniently
+ reviewing patches that people have attached to
+ [%+ terms.Bugzilla %]. <a href="http://fishsoup.net/software/splinter">More
+ information about Splinter</a>.
+</p>
+<h3>The patch review view</h3>
+<p>
+ If you get to Splinter by clicking on a link next to an
+ attachment in [% terms.Bugzilla %], you are presented with the patch
+ review view. This view has a number of different pages that can
+ be switched between with the links at the top of the screen.
+ The first page is the Overview page, the other pages correspond to
+ individual files changed by the review.
+</p>
+<p>
+ On the Overview page, from top to bottom are shown:
+</p>
+<ul>
+ <li>Introductory text to the patch. For a patch that was created
+ using 'git format-patch' this will be the Git commit
+ message.</li>
+ <li>Controls for creating a new review</li>
+ <li>Previous reviews that other people have written.</li>
+</ul>
+<p>
+ The pages for each file show a two-column view of the changes.
+ The left column is the previous contents of the file,
+ the right column is the new contents of the file. (If the file
+ is an entirely new file or an entirely deleted file, only one
+ column will be shown.) Red indicates lines that have been
+ removed, green lines that have been added, and blue lines that
+ were modified.
+</p>
+<p>
+ If people have previously made comments on individual lines of
+ the patch, they will show up both summarized on the Overview
+ page and also inline when looking at the files of the patch.
+</p>
+<h3>Reviewing an existing patch</h3>
+<p>
+ There are three components to a review:
+</p>
+<ul>
+ <li>
+ An overall comment. The text area on the first page allows
+ you to enter your overall thoughts on the [% terms.bug %].
+ </li>
+ <li>
+ Detailed comments on changes within the files. To comment on a
+ line in a patch, double click on it, and a text area will open
+ beneath that comment. When you are done, click the Save button
+ to save your comment or the Cancel button to throw your
+ comment away. You can double-click on a saved comment to start
+ editing it again and make further changes.
+ </li>
+ <li>
+ A change to the attachment status. (This is specific to
+ [%+ terms.Bugzilla %] instances that have attachment status, which is a
+ non-upstream patch. It's somewhat similar to attachment flags,
+ which splinter doesn't currently support displaying or
+ changing.) This allows you to mark a patch as read to commit
+ or needing additional work. This is done by changing the
+ drop-down next to the Publish button.
+ </li>
+</ul>
+<p>
+ Once you are done writing your review, go back to Overview page
+ and click the "Publish" button to submit it as a comment on the
+ [%+ terms.bug %]. The comment will have a link back to the review page so
+ that people can see your comments with the full context.
+</p>
+<h3>Saved drafts</h3>
+<p>
+ Whenever you start making changes, a draft is automatically
+ saved. If you come back to the patch review page for the same
+ attachment, that draft will automatically be resumed. Drafts are
+ not visible to anybody else until published.
+</p>
+<p>
+ Note that saving drafts requires the your browser to have support
+ for the "DOM Storage" standard. At time of writing, this is
+ available only in a few very recent browsers, like Firefox
+ 3.5. Strict privacy protections like disabling cookies may also
+ disable DOM Storage, since it provides another mechanism for
+ sites to track information about their users.
+</p>
+<h3>Responding to someone's review</h3>
+<p>
+ A response is treated just like any other review and created the
+ same way. A couple of features are helpful when responding: you
+ can double-click on an inline comment to respond to it. And on
+ the overview page, when you click on a detailed comment, you are
+ taken directly to the original location of the comment.
+</p>
+<h3>Uploading patches for review</h3>
+<p>
+ Splinter doesn't really care how patches are provided to
+ [%+ terms.Bugzilla %], as long as they are well-formatted patches. If you are
+ using Git for version control, you can either format changes as
+ patches
+ using <a href="http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html">'git
+ format-patch</a> and attach them manually to the [% terms.bug %], or you
+ can
+ use <a href="http://fishsoup.net/software/git-bz">git-bz</a>.
+ git-bz is highly recommended; it automates most of the steps
+ that Splinter can't handle: it files new [% terms.bugs %], attaches updated
+ attachments to existing [% terms.bugs %], and closes [% terms.bugs %] when you push the
+ corresponding git commits to your central repository.
+</p>
+<h3>The [% terms.bug %] review view</h3>
+<p>
+ Splinter also has a view where it shows all patches attached to
+ the [% terms.bug %] with their status and links to review them. You are
+ taken to this page after publishing a review. You can also get
+ to this page with the [% terms.bug %] link in the upper-right corner of the
+ patch review view.
+</p>
+<h3>Your reviews</h3>
+<p>
+ Splinter can also show you a list of all your draft and
+ published reviews. Access this page with the "Your reviews"
+ link at the bottom of the [% terms.bug %] review view. In-progress drafts
+ are shown in bold.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/Splinter/web/splinter.css b/extensions/Splinter/web/splinter.css
new file mode 100644
index 000000000..014751b08
--- /dev/null
+++ b/extensions/Splinter/web/splinter.css
@@ -0,0 +1,419 @@
+textarea:focus {
+ background: #f7f2d0;
+}
+
+#note {
+ background: #ffee88;
+ padding: 0.5em;
+}
+
+#error {
+ border: 1px solid black;
+ padding: 0.5em;
+ color: #bb0000;
+}
+
+#chooseReview {
+ margin-top: 1em;
+}
+
+.review-draft .review-desc, .review-draft .review-attachment {
+ font-weight: bold;
+}
+
+#bugInfo, #attachInfo {
+ margin-top: 0.5em;
+ margin-bottom: 1em;
+}
+
+#helpful-links {
+ float:right;
+}
+
+#chooseAttachment table {
+ margin-bottom: 1em;
+}
+
+#attachObsolete {
+ font-weight: bold;
+ color: #c00000;
+}
+
+.attachment-draft .attachment-id, .attachment-draft .attachment-desc {
+ font-weight: bold;
+}
+
+.attachment-obsolete .attachment-desc {
+ text-decoration: line-through ;
+}
+
+#navigation {
+ color: #888888;
+}
+
+.navigation-link {
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+.navigation-link-selected {
+ color: black;
+}
+
+#haveDraftNotice {
+ float: right;
+ color: #bb0000;
+ font-weight: bold;
+}
+
+#overview {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+#patchIntro {
+ border: 1px solid #888888;
+ font-size: 90%;
+ margin-bottom: 1em;
+ padding: 0.5em;
+}
+
+.reviewer-box {
+ padding: 0.5em;
+}
+
+.reviewer-0 .reviewer-box {
+ border-left: 10px solid green;
+}
+
+.reviewer-1 .reviewer-box {
+ border-left: 10px solid blue;
+}
+
+.reviewer-2 .reviewer-box {
+ border-left: 10px solid red;
+}
+
+.reviewer-3 .reviewer-box {
+ border-left: 10px solid yellow;
+}
+
+.reviewer-4 .reviewer-box {
+ border-left: 10px solid purple;
+}
+
+.reviewer-5 .reviewer-box {
+ border-left: 10px solid orange;
+}
+
+.reviewer {
+ float: left;
+}
+
+.review-date {
+ float: right;
+}
+
+.review-info-bottom {
+ clear: both;
+}
+
+.review {
+ border: 1px solid black;
+ font-size: 90%;
+ margin-top: 0.25em;
+ margin-bottom: 1em;
+}
+
+.review-intro {
+ margin-top: 0.5em;
+}
+
+.review-patch-file {
+ margin-top: 0.5em;
+ font-weight: bold;
+}
+
+.review-patch-comment {
+ border: 1px solid white;
+ padding: 1px;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ cursor: pointer;
+}
+
+.review-patch-comment:hover {
+ border: 1px solid #8888ff;
+}
+
+.review-patch-comment .file-table {
+ width: 50%;
+}
+
+.review-patch-comment .file-table-changed {
+ width: 100%;
+}
+
+.review-patch-comment-separator {
+ margin: 0.5em;
+ border-bottom: 1px solid #888888;
+}
+
+div.review-patch-comment-text {
+ margin-left: 2em;
+}
+
+.review-patch-comment .reviewer-box {
+ border-left-width: 4px;
+}
+
+#restored {
+ color: #bb0000;
+ margin-bottom: 0.5em;
+}
+
+#myCommentFrame {
+ margin-top: 0.25em;
+ position: relative;
+ border: 1px solid black;
+ padding-right: 8px; /* compensate for child's padding */
+}
+
+#myComment {
+ border: 0px solid black;
+ padding: 4px;
+ margin: 0px;
+ width: 100%;
+ height: 10em;
+}
+
+#emptyCommentNotice {
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ color: #888888;
+}
+
+#myPatchComments {
+ border: 1px solid black;
+ border-top-width: 0px;
+ padding: 0.5em;
+ font-size: 90%;
+}
+
+#buttonBox {
+ margin-top: 0.5em;
+ float: right;
+}
+
+.clear {
+ clear: both;
+}
+
+/* Used for IE <= 7, overridden for modern browsers */
+.pre-wrap {
+ white-space: pre;
+ word-wrap: break-word;
+}
+
+.pre-wrap {
+ white-space: pre-wrap;
+}
+
+#files {
+ position: relative;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+.file-label {
+ margin-top: 1em;
+ margin-bottom: 0.5em;
+}
+
+.file-label-name {
+ font-weight: bold;
+}
+
+.hunk-header td {
+ background: #ddccbb;
+ font-family: "DejaVu Sans Mono", monospace;
+ font-size: 80%;
+}
+
+.hunk-cell {
+ padding: 2px;
+}
+
+.old-line, .new-line {
+ font-family: "DejaVu Sans Mono", monospace;
+ font-size: 80%;
+ white-space: pre-wrap; /* CSS 3 & 2.1 */
+ white-space: -moz-pre-wrap; /* Gecko */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+}
+
+.removed-line {
+ background: #ffccaa;;
+}
+
+.added-line {
+ background: #bbffbb;
+}
+
+.changed-line {
+ background: #aaccff;
+}
+
+.file-table {
+ width: 100%;
+ border-collapse: collapse;
+ table-layout: fixed;
+}
+
+.line-number {
+ font-size: 80%;
+ text-align: right;
+ padding-right: 0.25em;
+ color: #888888;
+ -moz-user-select: none;
+}
+
+.line-number-column {
+ width: 2em;
+}
+
+.file-table-wide-numbers .line-number-column {
+ width: 3em;
+}
+
+.middle-column {
+ width: 3px;
+}
+
+.file-table-changed .comment-removed {
+ width: 50%;
+ float: left;
+}
+
+.file-table-changed .comment-changed {
+ margin-left: 25%;
+ margin-right: 25%;
+ clear: both;
+}
+
+.file-table-changed .comment-added {
+ width: 50%;
+ float: right;
+}
+
+.comment-frame {
+ border: 1px solid black;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ margin-left: 2em;
+}
+
+.file-table-wide-numbers .comment-frame {
+ margin-left: 3em;
+}
+
+.comment .review-info {
+ margin-top: 0.5em;
+ font-size: 80%;
+}
+
+#commentTextFrame {
+ border: 1px solid #ffeeaa;
+ margin-bottom: 5px;
+}
+
+#commentEditor.focused #commentTextFrame {
+ border: 1px solid #8888bb;
+}
+
+#commentEditorInner {
+ background: #ffeeaa;
+ padding: 0.5em;
+ margin-left: 2em;
+}
+
+.file-table-wide-numbers #commentEditorInner {
+ margin-left: 3em;
+}
+
+#commentEditor textarea {
+ width: 100%;
+ height: 10em;
+ border: 0px;
+}
+
+#commentEditor textarea:focus {
+ background: white;
+}
+
+#commentEditorLeftButtons {
+ float: left;
+}
+
+#commentEditorLeftButtons input {
+ margin-right: 0.5em;
+}
+
+#commentEditorRightButtons {
+ float: right;
+}
+
+.comment-separator-removed {
+ clear: left;
+}
+
+.comment-separator-added {
+ clear: right;
+}
+
+#saveDraftNotice {
+ border: 1px solid black;
+ padding: 0.5em;
+ background: #ffccaa;
+ position: fixed;
+ bottom: 0px;
+ right: 0px;
+}
+
+#credits {
+ font-size: 80%;
+ color: #888888;
+ padding: 10px;
+ text-align: center;
+}
+
+#quickHelpShow a, #quickHelpContent a {
+ text-decoration: none;
+}
+
+#quickHelpContent {
+ border: 1px solid #000;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ padding-left: 0.5em;
+ margin-bottom: 10px;
+}
+
+.file-label-collapse {
+ padding-right: 5px;
+ font-family: monospace;
+}
+
+.file-review-label {
+ font-size: 80%;
+}
+
+.file-reviewed-nav {
+ text-decoration: line-through;
+}
+
+.trailing-whitespace {
+ background: #ffaaaa;
+}
diff --git a/extensions/Splinter/web/splinter.js b/extensions/Splinter/web/splinter.js
new file mode 100644
index 000000000..18f445325
--- /dev/null
+++ b/extensions/Splinter/web/splinter.js
@@ -0,0 +1,2572 @@
+// Splinter - patch review add-on for Bugzilla
+// By Owen Taylor <otaylor@fishsoup.net>
+// Copyright 2009, Red Hat, Inc.
+// Licensed under MPL 1.1 or later, or GPL 2 or later
+// http://git.fishsoup.net/cgit/splinter
+// Converted to YUI by David Lawrence <dkl@mozilla.com>
+
+YAHOO.namespace('Splinter');
+
+var Dom = YAHOO.util.Dom;
+var Event = YAHOO.util.Event;
+var Splinter = YAHOO.Splinter;
+var Element = YAHOO.util.Element;
+
+Splinter.domCache = {
+ cache : [0],
+ expando : 'data' + new Date(),
+ data : function (elem) {
+ var cacheIndex = elem[Splinter.domCache.expando];
+ var nextCacheIndex = Splinter.domCache.cache.length;
+ if (!cacheIndex) {
+ cacheIndex = elem[Splinter.domCache.expando] = nextCacheIndex;
+ Splinter.domCache.cache[cacheIndex] = {};
+ }
+ return Splinter.domCache.cache[cacheIndex];
+ }
+};
+
+Splinter.Utils = {
+ assert : function(condition) {
+ if (!condition) {
+ throw new Error("Assertion failed");
+ }
+ },
+
+ assertNotReached : function() {
+ throw new Error("Assertion failed: should not be reached");
+ },
+
+ strip : function(string) {
+ return (/^\s*([\s\S]*?)\s*$/).exec(string)[1];
+ },
+
+ lstrip : function(string) {
+ return (/^\s*([\s\S]*)$/).exec(string)[1];
+ },
+
+ rstrip : function(string) {
+ return (/^([\s\S]*?)\s*$/).exec(string)[1];
+ },
+
+ formatDate : function(date, now) {
+ if (now == null) {
+ now = new Date();
+ }
+ var daysAgo = (now.getTime() - date.getTime()) / (24 * 60 * 60 * 1000);
+ if (daysAgo < 0 && now.getDate() != date.getDate()) {
+ return date.toLocaleDateString();
+ } else if (daysAgo < 1 && now.getDate() == date.getDate()) {
+ return date.toLocaleTimeString();
+ } else if (daysAgo < 7 && now.getDay() != date.getDay()) {
+ return ['Sun', 'Mon','Tue','Wed','Thu','Fri','Sat'][date.getDay()] + " " + date.toLocaleTimeString();
+ } else {
+ return date.toLocaleDateString();
+ }
+ },
+
+ preWrapLines : function(el, text) {
+ while ((m = Splinter.LINE_RE.exec(text)) != null) {
+ var div = document.createElement("div");
+ div.className = "pre-wrap";
+ div.appendChild(document.createTextNode(m[1].length == 0 ? " " : m[1]));
+ el.appendChild(div);
+ }
+ },
+
+ isDigits : function (str) {
+ return str.match(/^[0-9]+$/);
+ }
+};
+
+Splinter.Bug = {
+ TIMEZONES : {
+ CEST: '200',
+ CET: '100',
+ BST: '100',
+ GMT: '000',
+ UTC: '000',
+ EDT: '-400',
+ EST: '-500',
+ CDT: '-500',
+ CST: '-600',
+ MDT: '-600',
+ MST: '-700',
+ PDT: '-700',
+ PST: '-800'
+ },
+
+ parseDate : function(d) {
+ var m = /^\s*(\d+)-(\d+)-(\d+)\s+(\d+):(\d+)(?::(\d+))?\s+(?:([A-Z]{3,})|([-+]\d{3,}))\s*$/.exec(d);
+ if (!m) {
+ return null;
+ }
+
+ var year = parseInt(m[1], 10);
+ var month = parseInt(m[2] - 1, 10);
+ var day = parseInt(m[3], 10);
+ var hour = parseInt(m[4], 10);
+ var minute = parseInt(m[5], 10);
+ var second = m[6] ? parseInt(m[6], 10) : 0;
+
+ var tzoffset = 0;
+ if (m[7]) {
+ if (m[7] in Splinter.Bug.TIMEZONES) {
+ tzoffset = Splinter.Bug.TIMEZONES[m[7]];
+ }
+ } else {
+ tzoffset = parseInt(m[8], 10);
+ }
+
+ var unadjustedDate = new Date(Date.UTC(m[1], m[2] - 1, m[3], m[4], m[5]));
+
+ // 430 => 4:30. Easier to do this computation for only positive offsets
+ var sign = tzoffset < 0 ? -1 : 1;
+ tzoffset *= sign;
+ var adjustmentHours = Math.floor(tzoffset/100);
+ var adjustmentMinutes = tzoffset - adjustmentHours * 100;
+
+ return new Date(unadjustedDate.getTime() -
+ sign * adjustmentHours * 3600000 -
+ sign * adjustmentMinutes * 60000);
+ },
+
+ _formatWho : function(name, email) {
+ if (name && email) {
+ return name + " <" + email + ">";
+ } else if (name) {
+ return name;
+ } else {
+ return email;
+ }
+ }
+};
+
+Splinter.Bug.Attachment = function(bug, id) {
+ this._init(bug, id);
+};
+
+Splinter.Bug.Attachment.prototype = {
+ _init : function(bug, id) {
+ this.bug = bug;
+ this.id = id;
+ }
+};
+
+Splinter.Bug.Comment = function(bug) {
+ this._init(bug);
+};
+
+Splinter.Bug.Comment.prototype = {
+ _init : function(bug) {
+ this.bug = bug;
+ },
+
+ getWho : function() {
+ return Splinter.Bug._formatWho(this.whoName, this.whoEmail);
+ }
+};
+
+Splinter.Bug.Bug = function() {
+ this._init();
+};
+
+Splinter.Bug.Bug.prototype = {
+ _init : function() {
+ this.attachments = [];
+ this.comments = [];
+ },
+
+ getAttachment : function(attachmentId) {
+ var i;
+ for (i = 0; i < this.attachments.length; i++) {
+ if (this.attachments[i].id == attachmentId) {
+ return this.attachments[i];
+ }
+ }
+ return null;
+ },
+
+ getReporter : function() {
+ return Splinter.Bug._formatWho(this.reporterName, this.reporterEmail);
+ }
+};
+
+Splinter.Dialog = function() {
+ this._init.apply(this, arguments);
+};
+
+Splinter.Dialog.prototype = {
+ _init: function(prompt) {
+ this.buttons = [];
+ this.dialog = new YAHOO.widget.SimpleDialog('dialog', {
+ width: "300px",
+ fixedcenter: true,
+ visible: false,
+ modal: true,
+ draggable: false,
+ close: false,
+ hideaftersubmit: true,
+ constraintoviewport: true
+ });
+ this.dialog.setHeader(prompt);
+ },
+
+ addButton : function (label, callback, isdefault) {
+ this.buttons.push({ text : label,
+ handler : function () { this.hide(); callback(); },
+ isDefault : isdefault });
+ this.dialog.cfg.queueProperty("buttons", this.buttons);
+ },
+
+ show : function () {
+ this.dialog.render(document.body);
+ this.dialog.show();
+ }
+};
+
+Splinter.Patch = {
+ ADDED : 1 << 0,
+ REMOVED : 1 << 1,
+ CHANGED : 1 << 2,
+ NEW_NONEWLINE : 1 << 3,
+ OLD_NONEWLINE : 1 << 4,
+
+ FILE_START_RE : /^(?:(?:Index|index|===|RCS|diff).*\n)*\-\-\-[ \t]*(\S+).*\n\+\+\+[ \t]*(\S+).*\n(?=@@)/mg,
+ HUNK_START_RE : /^@@[ \t]+-(\d+),(\d+)[ \t]+\+(\d+),(\d+)[ \t]+@@(.*)\n/mg,
+ HUNK_RE : /((?:[ +\\-].*(?:\n|$))*)/mg,
+
+ GIT_FILE_RE : /^diff --git a\/(\S+).*\n(?:(new|deleted) file mode \d+\n)?(?:index.*\n)?GIT binary patch\n(delta )?/mg,
+
+ _cleanIntro : function(intro) {
+ var m;
+
+ intro = Splinter.Utils.strip(intro) + "\n\n";
+
+ // Git: remove binary diffs
+ var binary_re = /^(?:diff --git .*\n|literal \d+\n)(?:.+\n)+\n/mg;
+ m = binary_re.exec(intro);
+ while (m) {
+ intro = intro.substr(m.index + m[0].length);
+ binary_re.lastIndex = 0;
+ m = binary_re.exec(intro);
+ }
+
+ // Git: remove leading 'From <commit_id> <date>'
+ m = /^From\s+[a-f0-9]{40}.*\n/.exec(intro);
+ if (m) {
+ intro = intro.substr(m.index + m[0].length);
+ }
+
+ // Git: remove 'diff --stat' output from the end
+ m = /^---\n(?:^\s.*\n)+\s+\d+\s+files changed.*\n?(?!.)/m.exec(intro);
+ if (m) {
+ intro = intro.substr(0, m.index);
+ }
+
+ return Splinter.Utils.strip(intro);
+ }
+};
+
+Splinter.Patch.Hunk = function(oldStart, oldCount, newStart, newCount, functionLine, text) {
+ this._init(oldStart, oldCount, newStart, newCount, functionLine, text);
+};
+
+Splinter.Patch.Hunk.prototype = {
+ _init : function(oldStart, oldCount, newStart, newCount, functionLine, text) {
+ var rawlines = text.split("\n");
+ if (rawlines.length > 0 && Splinter.Utils.strip(rawlines[rawlines.length - 1]) == "") {
+ rawlines.pop(); // Remove trailing element from final \n
+ }
+
+ this.oldStart = oldStart;
+ this.oldCount = oldCount;
+ this.newStart = newStart;
+ this.newCount = newCount;
+ this.functionLine = Splinter.Utils.strip(functionLine);
+ this.comment = null;
+
+ var lines = [];
+ var totalOld = 0;
+ var totalNew = 0;
+
+ var currentStart = -1;
+ var currentOldCount = 0;
+ var currentNewCount = 0;
+
+ // A segment is a series of lines added/removed/changed with no intervening
+ // unchanged lines. We make the classification of Patch.ADDED/Patch.REMOVED/Patch.CHANGED
+ // in the flags for the entire segment
+ function startSegment() {
+ if (currentStart < 0) {
+ currentStart = lines.length;
+ }
+ }
+
+ function endSegment() {
+ if (currentStart >= 0) {
+ if (currentOldCount > 0 && currentNewCount > 0) {
+ var j;
+ for (j = currentStart; j < lines.length; j++) {
+ lines[j][2] &= ~(Splinter.Patch.ADDED | Splinter.Patch.REMOVED);
+ lines[j][2] |= Splinter.Patch.CHANGED;
+ }
+ }
+
+ currentStart = -1;
+ currentOldCount = 0;
+ currentNewCount = 0;
+ }
+ }
+
+ var i;
+ for (i = 0; i < rawlines.length; i++) {
+ var line = rawlines[i];
+ var op = line.substr(0, 1);
+ var strippedLine = line.substring(1);
+ var noNewLine = 0;
+ if (i + 1 < rawlines.length && rawlines[i + 1].substr(0, 1) == '\\') {
+ noNewLine = op == '-' ? Splinter.Patch.OLD_NONEWLINE : Splinter.Patch.NEW_NONEWLINE;
+ }
+
+ if (op == ' ') {
+ endSegment();
+ totalOld++;
+ totalNew++;
+ lines.push([strippedLine, strippedLine, 0]);
+ } else if (op == '-') {
+ totalOld++;
+ startSegment();
+ lines.push([strippedLine, null, Splinter.Patch.REMOVED | noNewLine]);
+ currentOldCount++;
+ } else if (op == '+') {
+ totalNew++;
+ startSegment();
+ if (currentStart + currentNewCount >= lines.length) {
+ lines.push([null, strippedLine, Splinter.Patch.ADDED | noNewLine]);
+ } else {
+ lines[currentStart + currentNewCount][1] = strippedLine;
+ lines[currentStart + currentNewCount][2] |= Splinter.Patch.ADDED | noNewLine;
+ }
+ currentNewCount++;
+ }
+ }
+
+ // git mail-formatted patches end with --\n<git version> like a signature
+ // This is troublesome since it looks like a subtraction at the end
+ // of last hunk of the last file. Handle this specifically rather than
+ // generically stripping excess lines to be kind to hand-edited patches
+ if (totalOld > oldCount &&
+ lines[lines.length - 1][1] == null &&
+ lines[lines.length - 1][0].substr(0, 1) == '-')
+ {
+ lines.pop();
+ currentOldCount--;
+ if (currentOldCount == 0 && currentNewCount == 0) {
+ currentStart = -1;
+ }
+ }
+
+ endSegment();
+
+ this.lines = lines;
+ },
+
+ iterate : function(cb) {
+ var i;
+ var oldLine = this.oldStart;
+ var newLine = this.newStart;
+ for (i = 0; i < this.lines.length; i++) {
+ var line = this.lines[i];
+ cb(this.location + i, oldLine, line[0], newLine, line[1], line[2], line);
+ if (line[0] != null) {
+ oldLine++;
+ }
+ if (line[1] != null) {
+ newLine++;
+ }
+ }
+ }
+};
+
+Splinter.Patch.File = function(filename, status, hunks) {
+ this._init(filename, status, hunks);
+};
+
+Splinter.Patch.File.prototype = {
+ _init : function(filename, status, hunks) {
+ this.filename = filename;
+ this.status = status;
+ this.hunks = hunks;
+ this.fileReviewed = false;
+
+ var l = 0;
+ var i;
+ for (i = 0; i < this.hunks.length; i++) {
+ var hunk = this.hunks[i];
+ hunk.location = l;
+ l += hunk.lines.length;
+ }
+ },
+
+ // A "location" is just a linear index into the lines of the patch in this file
+ getLocation : function(oldLine, newLine) {
+ var i;
+ for (i = 0; i < this.hunks.length; i++) {
+ var hunk = this.hunks[i];
+ if (oldLine != null && hunk.oldStart > oldLine) {
+ continue;
+ }
+ if (newLine != null && hunk.newStart > newLine) {
+ continue;
+ }
+
+ if ((oldLine != null && oldLine < hunk.oldStart + hunk.oldCount) ||
+ (newLine != null && newLine < hunk.newStart + hunk.newCount))
+ {
+ var location = -1;
+ hunk.iterate(function(loc, oldl, oldText, newl, newText, flags) {
+ if ((oldLine == null || oldl == oldLine) &&
+ (newLine == null || newl == newLine))
+ {
+ location = loc;
+ }
+ });
+
+ if (location != -1) {
+ return location;
+ }
+ }
+ }
+
+ throw "Bad oldLine,newLine: " + oldLine + "," + newLine;
+ },
+
+ getHunk : function(location) {
+ var i;
+ for (i = 0; i < this.hunks.length; i++) {
+ var hunk = this.hunks[i];
+ if (location >= hunk.location && location < hunk.location + hunk.lines.length) {
+ return hunk;
+ }
+ }
+
+ throw "Bad location: " + location;
+ },
+
+ toString : function() {
+ return "Splinter.Patch.File(" + this.filename + ")";
+ }
+};
+
+Splinter.Patch.Patch = function(text) {
+ this._init(text);
+};
+
+Splinter.Patch.Patch.prototype = {
+ // cf. parsing in Review.Review.parse()
+ _init : function(text) {
+ // Canonicalize newlines to simplify the following
+ if (/\r/.test(text)) {
+ text = text.replace(/(\r\n|\r|\n)/g, "\n");
+ }
+
+ this.files = [];
+
+ var m = Splinter.Patch.FILE_START_RE.exec(text);
+ var bm = Splinter.Patch.GIT_FILE_RE.exec(text);
+ if (m == null && bm == null)
+ throw "Not a patch";
+ this.intro = m == null ? '' : Splinter.Patch._cleanIntro(text.substring(0, m.index));
+
+ // show binary files in the intro
+
+ if (bm && this.intro.length)
+ this.intro += "\n\n";
+ while (bm != null) {
+ if (bm[2]) {
+ // added or deleted file
+ this.intro += bm[2].charAt(0).toUpperCase() + bm[2].slice(1) + ' Binary File: ' + bm[1] + "\n";
+ } else {
+ // delta
+ this.intro += 'Modified Binary File: ' + bm[1] + "\n";
+ }
+ bm = Splinter.Patch.GIT_FILE_RE.exec(text);
+ }
+
+ while (m != null) {
+ // git and hg show a diff between a/foo/bar.c and b/foo/bar.c
+ // or between a/foo/bar.c and /dev/null for removals and the
+ // reverse for additions.
+ var filename;
+ var status = undefined;
+
+ if (/^a\//.test(m[1]) && /^b\//.test(m[2])) {
+ filename = m[1].substring(2);
+ status = Splinter.Patch.CHANGED;
+ } else if (/^a\//.test(m[1]) && /^\/dev\/null/.test(m[2])) {
+ filename = m[1].substring(2);
+ status = Splinter.Patch.REMOVED;
+ } else if (/^\/dev\/null/.test(m[1]) && /^b\//.test(m[2])) {
+ filename = m[2].substring(2);
+ status = Splinter.Patch.ADDED;
+ // Handle non-git and non-hg cases as well
+ } else if (!/^\/dev\/null/.test(m[1]) && /^\/dev\/null/.test(m[2])) {
+ filename = m[1];
+ status = Splinter.Patch.REMOVED;
+ } else if (/^\/dev\/null/.test(m[1]) && !/^\/dev\/null/.test(m[2])) {
+ filename = m[2];
+ status = Splinter.Patch.ADDED;
+ } else {
+ filename = m[1];
+ }
+
+ var hunks = [];
+ var pos = Splinter.Patch.FILE_START_RE.lastIndex;
+ while (true) {
+ Splinter.Patch.HUNK_START_RE.lastIndex = pos;
+ var m2 = Splinter.Patch.HUNK_START_RE.exec(text);
+ if (m2 == null || m2.index != pos) {
+ break;
+ }
+
+ var oldStart = parseInt(m2[1], 10);
+ var oldCount = parseInt(m2[2], 10);
+ var newStart = parseInt(m2[3], 10);
+ var newCount = parseInt(m2[4], 10);
+
+ pos = Splinter.Patch.HUNK_START_RE.lastIndex;
+ Splinter.Patch.HUNK_RE.lastIndex = pos;
+ var m3 = Splinter.Patch.HUNK_RE.exec(text);
+ if (m3 == null || m3.index != pos) {
+ break;
+ }
+
+ pos = Splinter.Patch.HUNK_RE.lastIndex;
+ hunks.push(new Splinter.Patch.Hunk(oldStart, oldCount, newStart, newCount, m2[5], m3[1]));
+ }
+
+ if (status === undefined) {
+ // For non-Hg/Git we use assume patch was generated non-zero context
+ // and just look at the patch to detect added/removed. Bzr actually
+ // says added/removed in the diff, but SVN/CVS don't
+ if (hunks.length == 1 && hunks[0].oldCount == 0) {
+ status = Splinter.Patch.ADDED;
+ } else if (hunks.length == 1 && hunks[0].newCount == 0) {
+ status = Splinter.Patch.REMOVED;
+ } else {
+ status = Splinter.Patch.CHANGED;
+ }
+ }
+
+ this.files.push(new Splinter.Patch.File(filename, status, hunks));
+
+ Splinter.Patch.FILE_START_RE.lastIndex = pos;
+ m = Splinter.Patch.FILE_START_RE.exec(text);
+ }
+ },
+
+ getFile : function(filename) {
+ var i;
+ for (i = 0; i < this.files.length; i++) {
+ if (this.files[i].filename == filename) {
+ return this.files[i];
+ }
+ }
+
+ return null;
+ }
+};
+
+Splinter.Review = {
+ _removeFromArray : function(a, element) {
+ var i;
+ for (i = 0; i < a.length; i++) {
+ if (a[i] === element) {
+ a.splice(i, 1);
+ return;
+ }
+ }
+ },
+
+ _noNewLine : function(flags, flag) {
+ return ((flags & flag) != 0) ? "\n\\ No newline at end of file" : "";
+ },
+
+ _lineInSegment : function(line) {
+ return (line[2] & (Splinter.Patch.ADDED | Splinter.Patch.REMOVED | Splinter.Patch.CHANGED)) != 0;
+ },
+
+ _compareSegmentLines : function(a, b) {
+ var op1 = a[0];
+ var op2 = b[0];
+ if (op1 == op2) {
+ return 0;
+ } else if (op1 == ' ') {
+ return -1;
+ } else if (op2 == ' ') {
+ return 1;
+ } else {
+ return op1 == '-' ? -1 : 1;
+ }
+ },
+
+ FILE_START_RE : /^:::[ \t]+(\S+)[ \t]*\n/mg,
+ HUNK_START_RE : /^@@[ \t]+(?:-(\d+),(\d+)[ \t]+)?(?:\+(\d+),(\d+)[ \t]+)?@@.*\n/mg,
+ HUNK_RE : /((?:(?!@@|:::).*\n?)*)/mg,
+ REVIEW_RE : /^\s*review\s+of\s+attachment\s+(\d+)\s*:\s*/i
+};
+
+Splinter.Review.Comment = function(file, location, type, comment) {
+ this._init(file, location, type, comment);
+};
+
+Splinter.Review.Comment.prototype = {
+ _init : function(file, location, type, comment) {
+ this.file = file;
+ this.type = type;
+ this.location = location;
+ this.comment = comment;
+ },
+
+ getHunk : function() {
+ return this.file.patchFile.getHunk(this.location);
+ },
+
+ getInReplyTo : function() {
+ var i;
+ var hunk = this.getHunk();
+ var line = hunk.lines[this.location - hunk.location];
+ for (i = 0; i < line.reviewComments.length; i++) {
+ var comment = line.reviewComments[0];
+ if (comment === this) {
+ return null;
+ }
+ if (comment.type == this.type) {
+ return comment;
+ }
+ }
+
+ return null;
+ },
+
+ remove : function() {
+ var hunk = this.getHunk();
+ var line = hunk.lines[this.location - hunk.location];
+ Splinter.Review._removeFromArray(this.file.comments, this);
+ Splinter.Review._removeFromArray(line.reviewComments, this);
+ }
+};
+
+Splinter.Review.File = function(review, patchFile) {
+ this._init(review, patchFile);
+};
+
+Splinter.Review.File.prototype = {
+ _init : function(review, patchFile) {
+ this.review = review;
+ this.patchFile = patchFile;
+ this.comments = [];
+ },
+
+ addComment : function(location, type, comment) {
+ var hunk = this.patchFile.getHunk(location);
+ var line = hunk.lines[location - hunk.location];
+ comment = new Splinter.Review.Comment(this, location, type, comment);
+ if (line.reviewComments == null) {
+ line.reviewComments = [];
+ }
+ line.reviewComments.push(comment);
+ var i;
+ for (i = 0; i <= this.comments.length; i++) {
+ if (i == this.comments.length ||
+ this.comments[i].location > location ||
+ (this.comments[i].location == location && this.comments[i].type > type)) {
+ this.comments.splice(i, 0, comment);
+ break;
+ } else if (this.comments[i].location == location &&
+ this.comments[i].type == type) {
+ throw "Two comments at the same location";
+ }
+ }
+
+ return comment;
+ },
+
+ getComment : function(location, type) {
+ var i;
+ for (i = 0; i < this.comments.length; i++) {
+ if (this.comments[i].location == location &&
+ this.comments[i].type == type)
+ {
+ return this.comments[i];
+ }
+ }
+
+ return null;
+ },
+
+ toString : function() {
+ var str = "::: " + this.patchFile.filename + "\n";
+ var first = true;
+
+ var i;
+ for (i = 0; i < this.comments.length; i++) {
+ if (first) {
+ first = false;
+ } else {
+ str += '\n';
+ }
+ var comment = this.comments[i];
+ var hunk = comment.getHunk();
+
+ // Find the range of lines we might want to show. That's everything in the
+ // same segment as the commented line, plus up two two lines of non-comment
+ // diff before.
+
+ var contextFirst = comment.location - hunk.location;
+ if (Splinter.Review._lineInSegment(hunk.lines[contextFirst])) {
+ while (contextFirst > 0 && Splinter.Review._lineInSegment(hunk.lines[contextFirst - 1])) {
+ contextFirst--;
+ }
+ }
+
+ var j;
+ for (j = 0; j < 5; j++) {
+ if (contextFirst > 0 && !Splinter.Review._lineInSegment(hunk.lines[contextFirst - 1])) {
+ contextFirst--;
+ }
+ }
+
+ // Now get the diff lines (' ', '-', '+' for that range of lines)
+
+ var patchOldStart = null;
+ var patchNewStart = null;
+ var patchOldLines = 0;
+ var patchNewLines = 0;
+ var unchangedLines = 0;
+ var patchLines = [];
+
+ function addOldLine(oldLine) {
+ if (patchOldLines == 0) {
+ patchOldStart = oldLine;
+ }
+ patchOldLines++;
+ }
+
+ function addNewLine(newLine) {
+ if (patchNewLines == 0) {
+ patchNewStart = newLine;
+ }
+ patchNewLines++;
+ }
+
+ hunk.iterate(function(loc, oldLine, oldText, newLine, newText, flags) {
+ if (loc >= hunk.location + contextFirst && loc <= comment.location) {
+ if ((flags & (Splinter.Patch.ADDED | Splinter.Patch.REMOVED | Splinter.Patch.CHANGED)) == 0) {
+ patchLines.push('> ' + oldText + Splinter.Review._noNewLine(flags, Splinter.Patch.OLD_NONEWLINE | Splinter.Patch.NEW_NONEWLINE));
+ addOldLine(oldLine);
+ addNewLine(newLine);
+ unchangedLines++;
+ } else {
+ if ((comment.type == Splinter.Patch.REMOVED
+ || comment.type == Splinter.Patch.CHANGED)
+ && oldText != null)
+ {
+ patchLines.push('> -' + oldText +
+ Splinter.Review._noNewLine(flags, Splinter.Patch.OLD_NONEWLINE));
+ addOldLine(oldLine);
+ }
+ if ((comment.type == Splinter.Patch.ADDED
+ || comment.type == Splinter.Patch.CHANGED)
+ && newText != null)
+ {
+ patchLines.push('> +' + newText +
+ Splinter.Review._noNewLine(flags, Splinter.Patch.NEW_NONEWLINE));
+ addNewLine(newLine);
+ }
+ }
+ }
+ });
+
+ // Sort them into global order ' ', '-', '+'
+ patchLines.sort(Splinter.Review._compareSegmentLines);
+
+ // Completely blank context isn't useful so remove it; however if we are commenting
+ // on blank lines at the start of a segment, we have to leave something or things break
+ while (patchLines.length > 1 && patchLines[0].match(/^\s*$/)) {
+ patchLines.shift();
+ patchOldStart++;
+ patchNewStart++;
+ patchOldLines--;
+ patchNewLines--;
+ unchangedLines--;
+ }
+
+ if (comment.type == Splinter.Patch.CHANGED) {
+ // For a CHANGED comment, we have to show the the start of the hunk - but to save
+ // in length we can trim unchanged context before it
+
+ if (patchOldLines + patchNewLines - unchangedLines > 5) {
+ var toRemove = Math.min(unchangedLines, patchOldLines + patchNewLines - unchangedLines - 5);
+ patchLines.splice(0, toRemove);
+ patchOldStart += toRemove;
+ patchNewStart += toRemove;
+ patchOldLines -= toRemove;
+ patchNewLines -= toRemove;
+ unchangedLines -= toRemove;
+ }
+
+ str += '@@ -' + patchOldStart + ',' + patchOldLines + ' +' + patchNewStart + ',' + patchNewLines + ' @@\n';
+
+ // We will use up to 10 lines more:
+ // 5 old lines or 4 old lines and a "... <N> more ... " line
+ // 5 new lines or 4 new lines and a "... <N> more ... " line
+
+ var patchRemovals = patchOldLines - unchangedLines;
+ var showPatchRemovals = patchRemovals > 5 ? 4 : patchRemovals;
+ var patchAdditions = patchNewLines - unchangedLines;
+ var showPatchAdditions = patchAdditions > 5 ? 4 : patchAdditions;
+
+ j = 0;
+ while (j < unchangedLines + showPatchRemovals) {
+ str += "> " + patchLines[j] + "\n";
+ j++;
+ }
+ if (showPatchRemovals < patchRemovals) {
+ str += "> ... " + (patchRemovals - showPatchRemovals) + " more ...\n";
+ j += patchRemovals - showPatchRemovals;
+ }
+ while (j < unchangedLines + patchRemovals + showPatchAdditions) {
+ str += "> " + patchLines[j] + "\n";
+ j++;
+ }
+ if (showPatchAdditions < patchAdditions) {
+ str += "> ... " + (patchAdditions - showPatchAdditions) + " more ...\n";
+ j += patchAdditions - showPatchAdditions;
+ }
+ } else {
+ // We limit Patch.ADDED/Patch.REMOVED comments strictly to 5 lines after the header
+ if (patchOldLines + patchNewLines - unchangedLines > 5) {
+ var toRemove = patchOldLines + patchNewLines - unchangedLines - 5;
+ patchLines.splice(0, toRemove);
+ patchOldStart += toRemove;
+ patchNewStart += toRemove;
+ patchOldLines -= toRemove;
+ patchNewLines -= toRemove;
+ }
+
+ if (comment.type == Splinter.Patch.REMOVED) {
+ str += '@@ -' + patchOldStart + ',' + patchOldLines + ' @@\n';
+ } else {
+ str += '@@ +' + patchNewStart + ',' + patchNewLines + ' @@\n';
+ }
+ str += patchLines.join("\n") + "\n";
+ }
+ str += "\n" + comment.comment + "\n";
+ }
+
+ return str;
+ }
+};
+
+Splinter.Review.Review = function(patch, who, date) {
+ this._init(patch, who, date);
+};
+
+Splinter.Review.Review.prototype = {
+ _init : function(patch, who, date) {
+ this.date = null;
+ this.patch = patch;
+ this.who = who;
+ this.date = date;
+ this.intro = null;
+ this.files = [];
+
+ var i;
+ for (i = 0; i < patch.files.length; i++) {
+ this.files.push(new Splinter.Review.File(this, patch.files[i]));
+ }
+ },
+
+ // cf. parsing in Patch.Patch._init()
+ parse : function(text) {
+ Splinter.Review.FILE_START_RE.lastIndex = 0;
+ var m = Splinter.Review.FILE_START_RE.exec(text);
+
+ var intro;
+ if (m != null) {
+ this.setIntro(text.substr(0, m.index));
+ } else{
+ this.setIntro(text);
+ return;
+ }
+
+ while (m != null) {
+ var filename = m[1];
+ var file = this.getFile(filename);
+ if (file == null) {
+ throw "Review.Review refers to filename '" + filename + "' not in reviewed Patch.";
+ }
+
+ var pos = Splinter.Review.FILE_START_RE.lastIndex;
+
+ while (true) {
+ Splinter.Review.HUNK_START_RE.lastIndex = pos;
+ var m2 = Splinter.Review.HUNK_START_RE.exec(text);
+ if (m2 == null || m2.index != pos) {
+ break;
+ }
+
+ pos = Splinter.Review.HUNK_START_RE.lastIndex;
+
+ var oldStart, oldCount, newStart, newCount;
+ if (m2[1]) {
+ oldStart = parseInt(m2[1], 10);
+ oldCount = parseInt(m2[2], 10);
+ } else {
+ oldStart = oldCount = null;
+ }
+
+ if (m2[3]) {
+ newStart = parseInt(m2[3], 10);
+ newCount = parseInt(m2[4], 10);
+ } else {
+ newStart = newCount = null;
+ }
+
+ var type;
+ if (oldStart != null && newStart != null) {
+ type = Splinter.Patch.CHANGED;
+ } else if (oldStart != null) {
+ type = Splinter.Patch.REMOVED;
+ } else if (newStart != null) {
+ type = Splinter.Patch.ADDED;
+ } else {
+ throw "Either old or new line numbers must be given";
+ }
+
+ var oldLine = oldStart;
+ var newLine = newStart;
+
+ Splinter.Review.HUNK_RE.lastIndex = pos;
+ var m3 = Splinter.Review.HUNK_RE.exec(text);
+ if (m3 == null || m3.index != pos) {
+ break;
+ }
+
+ pos = Splinter.Review.HUNK_RE.lastIndex;
+
+ var rawlines = m3[1].split("\n");
+ if (rawlines.length > 0 && rawlines[rawlines.length - 1].match('^/s+$')) {
+ rawlines.pop(); // Remove trailing element from final \n
+ }
+
+ var commentText = null;
+
+ var lastSegmentOld = 0;
+ var lastSegmentNew = 0;
+ var i;
+ for (i = 0; i < rawlines.length; i++) {
+ var line = rawlines[i];
+ var count = 1;
+ if (i < rawlines.length - 1 && rawlines[i + 1].match(/^... \d+\s+/)) {
+ var m3 = /^\.\.\.\s+(\d+)\s+/.exec(rawlines[i + 1]);
+ count += parseInt(m3[1], 10);
+ i += 1;
+ }
+ // The check for /^$/ is because if Bugzilla is line-wrapping it also
+ // strips completely whitespace lines
+ if (line.match(/^>\s+/) || line.match(/^$/)) {
+ oldLine += count;
+ newLine += count;
+ lastSegmentOld = 0;
+ lastSegmentNew = 0;
+ } else if (line.match(/^(> )?-/)) {
+ oldLine += count;
+ lastSegmentOld += count;
+ } else if (line.match(/^(> )?\+/)) {
+ newLine += count;
+ lastSegmentNew += count;
+ } else if (line.match(/^\\/)) {
+ // '\ No newline at end of file' - ignore
+ } else {
+ if (console)
+ console.log("WARNING: Bad content in hunk: " + line);
+ if (line != 'NaN more ...') {
+ // Tack onto current comment even thou it's invalid
+ if (commentText == null) {
+ commentText = line;
+ } else {
+ commentText += "\n" + line;
+ }
+ }
+ }
+
+ if ((oldStart == null || oldLine == oldStart + oldCount) &&
+ (newStart == null || newLine == newStart + newCount))
+ {
+ commentText = rawlines.slice(i + 1).join("\n");
+ break;
+ }
+ }
+
+ if (commentText == null) {
+ if (console)
+ console.log("WARNING: No comment found in hunk");
+ commentText = "";
+ }
+
+
+ var location;
+ try {
+ if (type == Splinter.Patch.CHANGED) {
+ if (lastSegmentOld >= lastSegmentNew) {
+ oldLine--;
+ }
+ if (lastSegmentOld <= lastSegmentNew) {
+ newLine--;
+ }
+ location = file.patchFile.getLocation(oldLine, newLine);
+ } else if (type == Splinter.Patch.REMOVED) {
+ oldLine--;
+ location = file.patchFile.getLocation(oldLine, null);
+ } else if (type == Splinter.Patch.ADDED) {
+ newLine--;
+ location = file.patchFile.getLocation(null, newLine);
+ }
+ } catch(e) {
+ if (console)
+ console.error(e);
+ location = 0;
+ }
+ file.addComment(location, type, Splinter.Utils.strip(commentText));
+ }
+
+ Splinter.Review.FILE_START_RE.lastIndex = pos;
+ m = Splinter.Review.FILE_START_RE.exec(text);
+ }
+ },
+
+ setIntro : function (intro) {
+ intro = Splinter.Utils.strip(intro);
+ this.intro = intro != "" ? intro : null;
+ },
+
+ getFile : function (filename) {
+ var i;
+ for (i = 0; i < this.files.length; i++) {
+ if (this.files[i].patchFile.filename == filename) {
+ return this.files[i];
+ }
+ }
+
+ return null;
+ },
+
+ // Making toString() serialize to our seriaization format is maybe a bit sketchy
+ // But the serialization format is designed to be human readable so it works
+ // pretty well.
+ toString : function () {
+ var str = '';
+ if (this.intro != null) {
+ str += Splinter.Utils.strip(this.intro);
+ str += '\n';
+ }
+
+ var first = this.intro == null;
+ var i;
+ for (i = 0; i < this.files.length; i++) {
+ var file = this.files[i];
+ if (file.comments.length > 0) {
+ if (first) {
+ first = false;
+ } else {
+ str += '\n';
+ }
+ str += file.toString();
+ }
+ }
+
+ return str;
+ }
+};
+
+Splinter.ReviewStorage = {};
+
+Splinter.ReviewStorage.LocalReviewStorage = function() {
+ this._init();
+};
+
+Splinter.ReviewStorage.LocalReviewStorage.available = function() {
+ // The try is a workaround for
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=517778
+ // where if cookies are disabled or set to ask, then the first attempt
+ // to access the localStorage property throws a security error.
+ try {
+ return 'localStorage' in window && window.localStorage != null;
+ } catch (e) {
+ return false;
+ }
+};
+
+Splinter.ReviewStorage.LocalReviewStorage.prototype = {
+ _init : function() {
+ var reviewInfosText = localStorage.splinterReviews;
+ if (reviewInfosText == null) {
+ this._reviewInfos = [];
+ } else {
+ this._reviewInfos = YAHOO.lang.JSON.parse(reviewInfosText);
+ }
+ },
+
+ listReviews : function() {
+ return this._reviewInfos;
+ },
+
+ _reviewPropertyName : function(bug, attachment) {
+ return 'splinterReview_' + bug.id + '_' + attachment.id;
+ },
+
+ loadDraft : function(bug, attachment, patch) {
+ var propertyName = this._reviewPropertyName(bug, attachment);
+ var reviewText = localStorage[propertyName];
+ if (reviewText != null) {
+ var review = new Splinter.Review.Review(patch);
+ review.parse(reviewText);
+ return review;
+ } else {
+ return null;
+ }
+ },
+
+ _findReview : function(bug, attachment) {
+ var i;
+ for (i = 0 ; i < this._reviewInfos.length; i++) {
+ if (this._reviewInfos[i].bugId == bug.id && this._reviewInfos[i].attachmentId == attachment.id) {
+ return i;
+ }
+ }
+
+ return -1;
+ },
+
+ _updateOrCreateReviewInfo : function(bug, attachment, props) {
+ var reviewIndex = this._findReview(bug, attachment);
+ var reviewInfo;
+
+ var nowTime = Date.now();
+ if (reviewIndex >= 0) {
+ reviewInfo = this._reviewInfos[reviewIndex];
+ this._reviewInfos.splice(reviewIndex, 1);
+ } else {
+ reviewInfo = {
+ bugId: bug.id,
+ bugShortDesc: bug.shortDesc,
+ attachmentId: attachment.id,
+ attachmentDescription: attachment.description,
+ creationTime: nowTime
+ };
+ }
+
+ reviewInfo.modificationTime = nowTime;
+ for (var prop in props) {
+ reviewInfo[prop] = props[prop];
+ }
+
+ this._reviewInfos.push(reviewInfo);
+ localStorage.splinterReviews = YAHOO.lang.JSON.stringify(this._reviewInfos);
+ },
+
+ _deleteReviewInfo : function(bug, attachment) {
+ var reviewIndex = this._findReview(bug, attachment);
+ if (reviewIndex >= 0) {
+ this._reviewInfos.splice(reviewIndex, 1);
+ localStorage.splinterReviews = YAHOO.lang.JSON.stringify(this._reviewInfos);
+ }
+ },
+
+ saveDraft : function(bug, attachment, review, extraProps) {
+ var propertyName = this._reviewPropertyName(bug, attachment);
+ if (!extraProps) {
+ extraProps = {};
+ }
+ extraProps.isDraft = true;
+ this._updateOrCreateReviewInfo(bug, attachment, extraProps);
+ localStorage[propertyName] = "" + review;
+ },
+
+ deleteDraft : function(bug, attachment, review) {
+ var propertyName = this._reviewPropertyName(bug, attachment);
+
+ this._deleteReviewInfo(bug, attachment);
+ delete localStorage[propertyName];
+ },
+
+ draftPublished : function(bug, attachment) {
+ var propertyName = this._reviewPropertyName(bug, attachment);
+
+ this._updateOrCreateReviewInfo(bug, attachment, { isDraft: false });
+ delete localStorage[propertyName];
+ }
+};
+
+Splinter.saveDraftNoticeTimeoutId = null;
+Splinter.navigationLinks = {};
+Splinter.reviewers = {};
+Splinter.savingDraft = false;
+Splinter.UPDATE_ATTACHMENT_SUCCESS = /<title>\s*Changes\s+Submitted/;
+Splinter.LINE_RE = /(?!$)([^\r\n]*)(?:\r\n|\r|\n|$)/g;
+
+Splinter.displayError = function (msg) {
+ var el = new Element(document.createElement('p'));
+ el.appendChild(document.createTextNode(msg));
+ Dom.get('error').appendChild(Dom.get(el));
+ Dom.setStyle('error', 'display', 'block');
+};
+
+Splinter.publishReview = function () {
+ Splinter.saveComment();
+ Splinter.theReview.setIntro(Dom.get('myComment').value);
+
+ if (Splinter.reviewStorage) {
+ Splinter.reviewStorage.draftPublished(Splinter.theBug,
+ Splinter.theAttachment);
+ }
+
+ var publish_form = Dom.get('publish');
+ var publish_token = Dom.get('publish_token');
+ var publish_attach_id = Dom.get('publish_attach_id');
+ var publish_attach_desc = Dom.get('publish_attach_desc');
+ var publish_attach_filename = Dom.get('publish_attach_filename');
+ var publish_attach_contenttype = Dom.get('publish_attach_contenttype');
+ var publish_attach_ispatch = Dom.get('publish_attach_ispatch');
+ var publish_attach_isobsolete = Dom.get('publish_attach_isobsolete');
+ var publish_attach_isprivate = Dom.get('publish_attach_isprivate');
+ var publish_attach_status = Dom.get('publish_attach_status');
+ var publish_review = Dom.get('publish_review');
+
+ publish_token.value = Splinter.theAttachment.token;
+ publish_attach_id.value = Splinter.theAttachment.id;
+ publish_attach_desc.value = Splinter.theAttachment.description;
+ publish_attach_filename.value = Splinter.theAttachment.filename;
+ publish_attach_contenttype.value = Splinter.theAttachment.contenttypeentry;
+ publish_attach_ispatch.value = Splinter.theAttachment.isPatch;
+ publish_attach_isobsolete.value = Splinter.theAttachment.isObsolete;
+ publish_attach_isprivate.value = Splinter.theAttachment.isPrivate;
+
+ // This is a "magic string" used to identify review comments
+ if (Splinter.theReview.toString()) {
+ var comment = "Review of attachment " + Splinter.theAttachment.id + ":\n" +
+ "-----------------------------------------------------------------\n\n" +
+ Splinter.theReview.toString();
+ publish_review.value = comment;
+ }
+
+ if (Splinter.theAttachment.status
+ && Dom.get('attachmentStatus').value != Splinter.theAttachment.status)
+ {
+ publish_attach_status.value = Dom.get('attachmentStatus').value;
+ }
+
+ publish_form.submit();
+};
+
+Splinter.doDiscardReview = function () {
+ if (Splinter.theAttachment.status) {
+ Dom.get('attachmentStatus').value = Splinter.theAttachment.status;
+ }
+
+ Dom.get('myComment').value = '';
+ Dom.setStyle('emptyCommentNotice', 'display', 'block');
+
+ var i;
+ for (i = 0; i < Splinter.theReview.files.length; i++) {
+ while (Splinter.theReview.files[i].comments.length > 0) {
+ Splinter.theReview.files[i].comments[0].remove();
+ }
+ }
+
+ Splinter.updateMyPatchComments();
+ Splinter.updateHaveDraft();
+ Splinter.saveDraft();
+};
+
+Splinter.discardReview = function () {
+ var dialog = new Splinter.Dialog("Really discard your changes?");
+ dialog.addButton('No', function() {}, true);
+ dialog.addButton('Yes', Splinter.doDiscardReview, false);
+ dialog.show();
+};
+
+Splinter.haveDraft = function () {
+ if (Splinter.theAttachment.status && Dom.get('attachmentStatus').value != Splinter.theAttachment.status) {
+ return true;
+ }
+
+ if (Dom.get('myComment').value != '') {
+ return true;
+ }
+
+ var i;
+ for (i = 0; i < Splinter.theReview.files.length; i++) {
+ if (Splinter.theReview.files[i].comments.length > 0) {
+ return true;
+ }
+ }
+
+ for (i = 0; i < Splinter.thePatch.files.length; i++) {
+ if (Splinter.thePatch.files[i].fileReviewed) {
+ return true;
+ }
+ }
+
+ if (Splinter.flagChanged == 1) {
+ return true;
+ }
+
+ return false;
+};
+
+Splinter.updateHaveDraft = function () {
+ clearTimeout(Splinter.updateHaveDraftTimeoutId);
+ Splinter.updateHaveDraftTimeoutId = null;
+
+ if (Splinter.haveDraft()) {
+ Dom.get('publishButton').removeAttribute('disabled');
+ Dom.get('cancelButton').removeAttribute('disabled');
+ Dom.setStyle('haveDraftNotice', 'display', 'block');
+ } else {
+ Dom.get('publishButton').setAttribute('disabled', 'true');
+ Dom.get('cancelButton').setAttribute('disabled', 'true');
+ Dom.setStyle('haveDraftNotice', 'display', 'none');
+ }
+};
+
+Splinter.queueUpdateHaveDraft = function () {
+ if (Splinter.updateHaveDraftTimeoutId == null) {
+ Splinter.updateHaveDraftTimeoutId = setTimeout(Splinter.updateHaveDraft, 0);
+ }
+};
+
+Splinter.hideSaveDraftNotice = function () {
+ clearTimeout(Splinter.saveDraftNoticeTimeoutId);
+ Splinter.saveDraftNoticeTimeoutId = null;
+ Dom.setStyle('saveDraftNotice', 'display', 'none');
+};
+
+Splinter.saveDraft = function () {
+ if (Splinter.reviewStorage == null) {
+ return;
+ }
+
+ clearTimeout(Splinter.saveDraftTimeoutId);
+ Splinter.saveDraftTimeoutId = null;
+
+ Splinter.savingDraft = true;
+ Dom.get('saveDraftNotice').innerHTML = "Saving Draft...";
+ Dom.setStyle('saveDraftNotice', 'display', 'block');
+ clearTimeout(Splinter.saveDraftNoticeTimeoutId);
+ setTimeout(Splinter.hideSaveDraftNotice, 3000);
+
+ if (Splinter.currentEditComment) {
+ Splinter.currentEditComment.comment = Splinter.Utils.strip(Dom.get("commentEditor").getElementsByTagName("textarea")[0].value);
+ // Messy, we don't want the empty comment in the saved draft, so remove it and
+ // then add it back.
+ if (!Splinter.currentEditComment.comment) {
+ Splinter.currentEditComment.remove();
+ }
+ }
+
+ Splinter.theReview.setIntro(Dom.get('myComment').value);
+
+ var draftSaved = false;
+ if (Splinter.haveDraft()) {
+ var filesReviewed = {};
+ for (var i = 0; i < Splinter.thePatch.files.length; i++) {
+ var file = Splinter.thePatch.files[i];
+ if (file.fileReviewed) {
+ filesReviewed[file.filename] = true;
+ }
+ }
+ Splinter.reviewStorage.saveDraft(Splinter.theBug, Splinter.theAttachment, Splinter.theReview,
+ { 'filesReviewed' : filesReviewed });
+ draftSaved = true;
+ } else {
+ Splinter.reviewStorage.deleteDraft(Splinter.theBug, Splinter.theAttachment, Splinter.theReview);
+ }
+
+ if (Splinter.currentEditComment && !Splinter.currentEditComment.comment) {
+ Splinter.currentEditComment = Splinter.currentEditComment.file.addComment(Splinter.currentEditComment.location,
+ Splinter.currentEditComment.type, "");
+ }
+
+ Splinter.savingDraft = false;
+ if (draftSaved) {
+ Dom.get('saveDraftNotice').innerHTML = "Saved Draft";
+ } else {
+ Splinter.hideSaveDraftNotice();
+ }
+};
+
+Splinter.queueSaveDraft = function () {
+ if (Splinter.saveDraftTimeoutId == null) {
+ Splinter.saveDraftTimeoutId = setTimeout(Splinter.saveDraft, 10000);
+ }
+};
+
+Splinter.flushSaveDraft = function () {
+ if (Splinter.saveDraftTimeoutId != null) {
+ Splinter.saveDraft();
+ }
+};
+
+Splinter.ensureCommentArea = function (row) {
+ var file = Splinter.domCache.data(row).patchFile;
+ var colSpan = file.status == Splinter.Patch.CHANGED ? 5 : 2;
+
+ if (!row.nextSibling || row.nextSibling.className != "comment-area") {
+ var tr = new Element(document.createElement('tr'));
+ Dom.addClass(tr, 'comment-area');
+ var td = new Element(document.createElement('td'));
+ Dom.setAttribute(td, 'colspan', colSpan);
+ td.appendTo(tr);
+ Dom.insertAfter(tr, row);
+ }
+
+ return row.nextSibling.firstChild;
+};
+
+Splinter.getTypeClass = function (type) {
+ switch (type) {
+ case Splinter.Patch.ADDED:
+ return "comment-added";
+ case Splinter.Patch.REMOVED:
+ return "comment-removed";
+ case Splinter.Patch.CHANGED:
+ return "comment-changed";
+ }
+
+ return null;
+};
+
+Splinter.getSeparatorClass = function (type) {
+ switch (type) {
+ case Splinter.Patch.ADDED:
+ return "comment-separator-added";
+ case Splinter.Patch.REMOVED:
+ return "comment-separator-removed";
+ }
+
+ return null;
+};
+
+Splinter.getReviewerClass = function (review) {
+ var reviewerIndex;
+ if (review == Splinter.theReview) {
+ reviewerIndex = 0;
+ } else {
+ reviewerIndex = (Splinter.reviewers[review.who] - 1) % 5 + 1;
+ }
+
+ return "reviewer-" + reviewerIndex;
+};
+
+Splinter.addCommentDisplay = function (commentArea, comment) {
+ var review = comment.file.review;
+
+ var separatorClass = Splinter.getSeparatorClass(comment.type);
+ if (separatorClass) {
+ var div = new Element(document.createElement('div'));
+ Dom.addClass(div, separatorClass);
+ Dom.addClass(div, Splinter.getReviewerClass(review));
+ div.appendTo(commentArea);
+ }
+
+ var commentDiv = new Element(document.createElement('div'));
+ Dom.addClass(commentDiv, 'comment');
+ Dom.addClass(commentDiv, Splinter.getTypeClass(comment.type));
+ Dom.addClass(commentDiv, Splinter.getReviewerClass(review));
+
+ Event.addListener(Dom.get(commentDiv), 'dblclick', function () {
+ Splinter.saveComment();
+ Splinter.insertCommentEditor(commentArea, comment.file.patchFile,
+ comment.location, comment.type);
+ });
+
+ var commentFrame = new Element(document.createElement('div'));
+ Dom.addClass(commentFrame, 'comment-frame');
+ commentFrame.appendTo(commentDiv);
+
+ var reviewerBox = new Element(document.createElement('div'));
+ Dom.addClass(reviewerBox, 'reviewer-box');
+ reviewerBox.appendTo(commentFrame);
+
+ var commentText = new Element(document.createElement('div'));
+ Dom.addClass(commentText, 'comment-text');
+ Splinter.Utils.preWrapLines(commentText, comment.comment);
+ commentText.appendTo(reviewerBox);
+
+ commentDiv.appendTo(commentArea);
+
+ if (review != Splinter.theReview) {
+ var reviewInfo = new Element(document.createElement('div'));
+ Dom.addClass(reviewInfo, 'review-info');
+
+ var reviewer = new Element(document.createElement('div'));
+ Dom.addClass(reviewer, 'reviewer');
+ reviewer.appendChild(document.createTextNode(review.who));
+ reviewer.appendTo(reviewInfo);
+
+ var reviewDate = new Element(document.createElement('div'));
+ Dom.addClass(reviewDate, 'review-date');
+ reviewDate.appendChild(document.createTextNode(Splinter.Utils.formatDate(review.date)));
+ reviewDate.appendTo(reviewInfo);
+
+ var reviewInfoBottom = new Element(document.createElement('div'));
+ Dom.addClass(reviewInfoBottom, 'review-info-bottom');
+ reviewInfoBottom.appendTo(reviewInfo);
+
+ reviewInfo.appendTo(reviewerBox);
+ }
+
+ comment.div = commentDiv;
+};
+
+Splinter.saveComment = function () {
+ var comment = Splinter.currentEditComment;
+ if (!comment) {
+ return;
+ }
+
+ var commentEditor = Dom.get('commentEditor');
+ var commentArea = commentEditor.parentNode;
+ var reviewFile = comment.file;
+
+ var hunk = comment.getHunk();
+ var line = hunk.lines[comment.location - hunk.location];
+
+ var value = Splinter.Utils.strip(commentEditor.getElementsByTagName('textarea')[0].value);
+ if (value != "") {
+ comment.comment = value;
+ Splinter.addCommentDisplay(commentArea, comment);
+ } else {
+ comment.remove();
+ }
+
+ if (line.reviewComments.length > 0) {
+ commentEditor.parentNode.removeChild(commentEditor);
+ var commentEditorSeparator = Dom.get('commentEditorSeparator');
+ if (commentEditorSeparator) {
+ commentEditorSeparator.parentNode.removeChild(commentEditorSeparator);
+ }
+ } else {
+ var parentToRemove = commentArea.parentNode;
+ commentArea.parentNode.parentNode.removeChild(parentToRemove);
+ }
+
+ Splinter.currentEditComment = null;
+ Splinter.saveDraft();
+ Splinter.queueUpdateHaveDraft();
+};
+
+Splinter.cancelComment = function (previousText) {
+ Dom.get("commentEditor").getElementsByTagName("textarea")[0].value = previousText;
+ Splinter.saveComment();
+};
+
+Splinter.deleteComment = function () {
+ Dom.get('commentEditor').getElementsByTagName('textarea')[0].value = "";
+ Splinter.saveComment();
+};
+
+Splinter.insertCommentEditor = function (commentArea, file, location, type) {
+ Splinter.saveComment();
+
+ var reviewFile = Splinter.theReview.getFile(file.filename);
+ var comment = reviewFile.getComment(location, type);
+ if (!comment) {
+ comment = reviewFile.addComment(location, type, "");
+ Splinter.queueUpdateHaveDraft();
+ }
+
+ var previousText = comment.comment;
+
+ var typeClass = Splinter.getTypeClass(type);
+ var separatorClass = Splinter.getSeparatorClass(type);
+
+ var nodes = Dom.getElementsByClassName('reviewer-0', 'div', commentArea);
+ var i;
+ for (i = 0; i < nodes.length; i++) {
+ if (separatorClass && Dom.hasClass(nodes[i], separatorClass)) {
+ nodes[i].parentNode.removeChild(nodes[i]);
+ }
+ if (Dom.hasClass(nodes[i], typeClass)) {
+ nodes[i].parentNode.removeChild(nodes[i]);
+ }
+ }
+
+ if (separatorClass) {
+ var commentEditorSeparator = new Element(document.createElement('div'));
+ commentEditorSeparator.set('id', 'commentEditorSeparator');
+ Dom.addClass(commentEditorSeparator, separatorClass);
+ commentEditorSeparator.appendTo(commentArea);
+ }
+
+ var commentEditor = new Element(document.createElement('div'));
+ Dom.setAttribute(commentEditor, 'id', 'commentEditor');
+ Dom.addClass(commentEditor, typeClass);
+ commentEditor.appendTo(commentArea);
+
+ var commentEditorInner = new Element(document.createElement('div'));
+ Dom.setAttribute(commentEditorInner, 'id', 'commentEditorInner');
+ commentEditorInner.appendTo(commentEditor);
+
+ var commentTextFrame = new Element(document.createElement('div'));
+ Dom.setAttribute(commentTextFrame, 'id', 'commentTextFrame');
+ commentTextFrame.appendTo(commentEditorInner);
+
+ var commentTextArea = new Element(document.createElement('textarea'));
+ Dom.setAttribute(commentTextArea, 'id', 'commentTextArea');
+ Dom.setAttribute(commentTextArea, 'tabindex', 1);
+ commentTextArea.appendChild(document.createTextNode(previousText));
+ commentTextArea.appendTo(commentTextFrame);
+ Event.addListener('commentTextArea', 'keydown', function (e) {
+ if (e.which == 13 && e.ctrlKey) {
+ Splinter.saveComment();
+ } else if (e.which == 27) {
+ var comment = Dom.get('commentTextArea').value;
+ if (previousText == comment || comment == '') {
+ Splinter.cancelComment(previousText);
+ }
+ } else {
+ Splinter.queueSaveDraft();
+ }
+ });
+ Event.addListener('commentTextArea', 'focusin', function () { Dom.addClass(commentEditor, 'focused'); });
+ Event.addListener('commentTextArea', 'focusout', function () { Dom.removeClass(commentEditor, 'focused'); });
+ Dom.get(commentTextArea).focus();
+
+ var commentEditorLeftButtons = new Element(document.createElement('div'));
+ commentEditorLeftButtons.set('id', 'commentEditorLeftButtons');
+ commentEditorLeftButtons.appendTo(commentEditorInner);
+
+ var commentCancel = new Element(document.createElement('input'));
+ commentCancel.set('id','commentCancel');
+ commentCancel.set('type', 'button');
+ commentCancel.set('value', 'Cancel');
+ Dom.setAttribute(commentCancel, 'tabindex', 4);
+ commentCancel.appendTo(commentEditorLeftButtons);
+ Event.addListener('commentCancel', 'click', function () { Splinter.cancelComment(previousText); });
+
+ if (previousText) {
+ var commentDelete = new Element(document.createElement('input'));
+ commentDelete.set('id','commentDelete');
+ commentDelete.set('type', 'button');
+ commentDelete.set('value', 'Delete');
+ Dom.setAttribute(commentDelete, 'tabindex', 3);
+ commentDelete.appendTo(commentEditorLeftButtons);
+ Event.addListener('commentDelete', 'click', Splinter.deleteComment);
+ }
+
+ var commentEditorRightButtons = new Element(document.createElement('div'));
+ commentEditorRightButtons.set('id', 'commentEditorRightButtons');
+ commentEditorRightButtons.appendTo(commentEditorInner);
+
+ var commentSave = new Element(document.createElement('input'));
+ commentSave.set('id','commentSave');
+ commentSave.set('type', 'button');
+ commentSave.set('value', 'Save');
+ Dom.setAttribute(commentSave, 'tabindex', 2);
+ commentSave.appendTo(commentEditorRightButtons);
+ Event.addListener('commentSave', 'click', Splinter.saveComment);
+
+ var clear = new Element(document.createElement('div'));
+ Dom.addClass(clear, 'clear');
+ clear.appendTo(commentEditorInner);
+
+ Splinter.currentEditComment = comment;
+};
+
+Splinter.insertCommentForRow = function (clickRow, clickType) {
+ var file = Splinter.domCache.data(clickRow).patchFile;
+ var clickLocation = Splinter.domCache.data(clickRow).patchLocation;
+
+ var row = clickRow;
+ var location = clickLocation;
+ var type = clickType;
+
+ Splinter.saveComment();
+ var commentArea = Splinter.ensureCommentArea(row);
+ Splinter.insertCommentEditor(commentArea, file, location, type);
+};
+
+Splinter.EL = function (element, cls, text, title) {
+ var e = document.createElement(element);
+ if (text != null) {
+ e.appendChild(document.createTextNode(text));
+ }
+ if (cls) {
+ e.className = cls;
+ }
+ if (title) {
+ Dom.setAttribute(e, 'title', title);
+ }
+
+ return e;
+};
+
+Splinter.textTD = function (cls, text, title) {
+ if (text == "") {
+ return Splinter.EL("td", cls, "\u00a0", title);
+ }
+ var m = text.match(/^(.*?)(\s+)$/);
+ if (m) {
+ var td = Splinter.EL("td", cls, m[1], title);
+ td.insertBefore(Splinter.EL("span", cls + " trailing-whitespace", m[2], title), null);
+ return td;
+ } else {
+ return Splinter.EL("td", cls, text, title);
+ }
+}
+
+Splinter.getElementPosition = function (element) {
+ var left = element.offsetLeft;
+ var top = element.offsetTop;
+ var parent = element.offsetParent;
+ while (parent && parent != document.body) {
+ left += parent.offsetLeft;
+ top += parent.offsetTop;
+ parent = parent.offsetParent;
+ }
+
+ return [left, top];
+};
+
+Splinter.scrollToElement = function (element) {
+ var windowHeight;
+ if ('innerHeight' in window) { // Not IE
+ windowHeight = window.innerHeight;
+ } else { // IE
+ windowHeight = document.documentElement.clientHeight;
+ }
+ var pos = Splinter.getElementPosition(element);
+ var yCenter = pos[1] + element.offsetHeight / 2;
+ window.scrollTo(0, yCenter - windowHeight / 2);
+};
+
+Splinter.onRowDblClick = function (e) {
+ var file = Splinter.domCache.data(this).patchFile;
+ var type;
+
+ if (file.status == Splinter.Patch.CHANGED) {
+ var pos = Splinter.getElementPosition(this);
+ var delta = e.pageX - (pos[0] + this.offsetWidth/2);
+ if (delta < - 20) {
+ type = Splinter.Patch.REMOVED;
+ } else if (delta < 20) {
+ // CHANGED comments disabled due to breakage
+ // type = Splinter.Patch.CHANGED;
+ type = Splinter.Patch.ADDED;
+ } else {
+ type = Splinter.Patch.ADDED;
+ }
+ } else {
+ type = file.status;
+ }
+
+ Splinter.insertCommentForRow(this, type);
+};
+
+Splinter.appendPatchTable = function (type, maxLine, parentDiv) {
+ var fileTableContainer = new Element(document.createElement('div'));
+ Dom.addClass(fileTableContainer, 'file-table-container');
+ fileTableContainer.appendTo(parentDiv);
+
+ var fileTable = new Element(document.createElement('table'));
+ Dom.addClass(fileTable, 'file-table');
+ fileTable.appendTo(fileTableContainer);
+
+ var colQ = new Element(document.createElement('colgroup'));
+ colQ.appendTo(fileTable);
+
+ var col1, col2;
+ if (type != Splinter.Patch.ADDED) {
+ col1 = new Element(document.createElement('col'));
+ Dom.addClass(col1, 'line-number-column');
+ Dom.setAttribute(col1, 'span', '1');
+ col1.appendTo(colQ);
+ col2 = new Element(document.createElement('col'));
+ Dom.addClass(col2, 'old-column');
+ Dom.setAttribute(col2, 'span', '1');
+ col2.appendTo(colQ);
+ }
+ if (type == Splinter.Patch.CHANGED) {
+ col1 = new Element(document.createElement('col'));
+ Dom.addClass(col1, 'middle-column');
+ Dom.setAttribute(col1, 'span', '1');
+ col1.appendTo(colQ);
+ }
+ if (type != Splinter.Patch.REMOVED) {
+ col1 = new Element(document.createElement('col'));
+ Dom.addClass(col1, 'line-number-column');
+ Dom.setAttribute(col1, 'span', '1');
+ col1.appendTo(colQ);
+ col2 = new Element(document.createElement('col'));
+ Dom.addClass(col2, 'new-column');
+ Dom.setAttribute(col2, 'span', '1');
+ col2.appendTo(colQ);
+ }
+
+ if (type == Splinter.Patch.CHANGED) {
+ Dom.addClass(fileTable, 'file-table-changed');
+ }
+
+ if (maxLine >= 1000) {
+ Dom.addClass(fileTable, "file-table-wide-numbers");
+ }
+
+ var tbody = new Element(document.createElement('tbody'));
+ tbody.appendTo(fileTable);
+
+ return tbody;
+};
+
+Splinter.appendPatchHunk = function (file, hunk, tableType, includeComments, clickable, tbody, filter) {
+ hunk.iterate(function(loc, oldLine, oldText, newLine, newText, flags, line) {
+ if (filter && !filter(loc)) {
+ return;
+ }
+
+ var tr = document.createElement("tr");
+
+ var oldStyle = "";
+ var newStyle = "";
+ if ((flags & Splinter.Patch.CHANGED) != 0) {
+ oldStyle = newStyle = "changed-line";
+ } else if ((flags & Splinter.Patch.REMOVED) != 0) {
+ oldStyle = "removed-line";
+ } else if ((flags & Splinter.Patch.ADDED) != 0) {
+ newStyle = "added-line";
+ }
+
+ var title = "Double click the line to add a review comment";
+
+ if (tableType != Splinter.Patch.ADDED) {
+ if (oldText != null) {
+ tr.appendChild(Splinter.EL("td", "line-number", oldLine.toString(), title));
+ tr.appendChild(Splinter.textTD("old-line " + oldStyle, oldText, title));
+ oldLine++;
+ } else {
+ tr.appendChild(Splinter.EL("td", "line-number"));
+ tr.appendChild(Splinter.EL("td", "old-line"));
+ }
+ }
+
+ if (tableType == Splinter.Patch.CHANGED) {
+ tr.appendChild(Splinter.EL("td", "line-middle"));
+ }
+
+ if (tableType != Splinter.Patch.REMOVED) {
+ if (newText != null) {
+ tr.appendChild(Splinter.EL("td", "line-number", newLine.toString(), title));
+ tr.appendChild(Splinter.textTD("new-line " + newStyle, newText, title));
+ newLine++;
+ } else if (tableType == Splinter.Patch.CHANGED) {
+ tr.appendChild(Splinter.EL("td", "line-number"));
+ tr.appendChild(Splinter.EL("td", "new-line"));
+ }
+ }
+
+ if (clickable) {
+ Splinter.domCache.data(tr).patchFile = file;
+ Splinter.domCache.data(tr).patchLocation = loc;
+ Event.addListener(tr, 'dblclick', Splinter.onRowDblClick);
+ }
+
+ tbody.appendChild(tr);
+
+ if (includeComments && line.reviewComments != null) {
+ var k;
+ for (k = 0; k < line.reviewComments.length; k++) {
+ var commentArea = Splinter.ensureCommentArea(tr);
+ Splinter.addCommentDisplay(commentArea, line.reviewComments[k]);
+ }
+ }
+ });
+};
+
+Splinter.addPatchFile = function (file) {
+ var fileDiv = new Element(document.createElement('div'));
+ Dom.addClass(fileDiv, 'file');
+ fileDiv.appendTo(Dom.get('files'));
+ file.div = fileDiv;
+
+ var statusString;
+ switch (file.status) {
+ case Splinter.Patch.ADDED:
+ statusString = " (new file)";
+ break;
+ case Splinter.Patch.REMOVED:
+ statusString = " (removed)";
+ break;
+ case Splinter.Patch.CHANGED:
+ statusString = "";
+ break;
+ }
+
+ var fileLabel = new Element(document.createElement('div'));
+ Dom.addClass(fileLabel, 'file-label');
+ fileLabel.appendTo(fileDiv);
+
+ var fileCollapseLink = new Element(document.createElement('a'));
+ Dom.addClass(fileCollapseLink, 'file-label-collapse');
+ fileCollapseLink.appendChild(document.createTextNode('[-]'));
+ Dom.setAttribute(fileCollapseLink, 'href', 'javascript:void(0);')
+ Dom.setAttribute(fileCollapseLink, 'onclick', "Splinter.toggleCollapsed('" +
+ encodeURIComponent(file.filename) + "');");
+ Dom.setAttribute(fileCollapseLink, 'title', 'Click to expand or collapse this file table');
+ fileCollapseLink.appendTo(fileLabel);
+
+ var fileLabelName = new Element(document.createElement('span'));
+ Dom.addClass(fileLabelName, 'file-label-name');
+ fileLabelName.appendChild(document.createTextNode(file.filename));
+ fileLabelName.appendTo(fileLabel);
+
+ var fileLabelStatus = new Element(document.createElement('span'));
+ Dom.addClass(fileLabelStatus, 'file-label-status');
+ fileLabelStatus.appendChild(document.createTextNode(statusString));
+ fileLabelStatus.appendTo(fileLabel);
+
+ var fileReviewed = new Element(document.createElement('span'));
+ Dom.addClass(fileReviewed, 'file-review');
+ Dom.setAttribute(fileReviewed, 'title', 'Indicates that a review has been completed for this file. ' +
+ 'This is for personal tracking purposes only and has no effect ' +
+ 'on the published review.');
+ fileReviewed.appendTo(fileLabel);
+
+ var fileReviewedInput = new Element(document.createElement('input'));
+ Dom.setAttribute(fileReviewedInput, 'type', 'checkbox');
+ Dom.setAttribute(fileReviewedInput, 'id', 'file-review-checkbox-' + encodeURIComponent(file.filename));
+ Dom.setAttribute(fileReviewedInput, 'onchange', "Splinter.toggleFileReviewed('" +
+ encodeURIComponent(file.filename) + "');");
+ if (file.fileReviewed) {
+ Dom.setAttribute(fileReviewedInput, 'checked', 'true');
+ }
+ fileReviewedInput.appendTo(fileReviewed);
+
+ var fileReviewedLabel = new Element(document.createElement('label'));
+ Dom.addClass(fileReviewedLabel, 'file-review-label')
+ Dom.setAttribute(fileReviewedLabel, 'for', 'file-review-checkbox-' + encodeURIComponent(file.filename));
+ fileReviewedLabel.appendChild(document.createTextNode(' Reviewed'));
+ fileReviewedLabel.appendTo(fileReviewed);
+
+ var lastHunk = file.hunks[file.hunks.length - 1];
+ var lastLine = Math.max(lastHunk.oldStart + lastHunk.oldCount - 1,
+ lastHunk.newStart + lastHunk.newCount - 1);
+
+ var tbody = Splinter.appendPatchTable(file.status, lastLine, fileDiv);
+
+ var i;
+ for (i = 0; i < file.hunks.length; i++) {
+ var hunk = file.hunks[i];
+ if (hunk.oldStart > 1) {
+ var hunkHeader = Splinter.EL("tr", "hunk-header");
+ tbody.appendChild(hunkHeader);
+ hunkHeader.appendChild(Splinter.EL("td")); // line number column
+ var hunkCell = Splinter.EL("td", "hunk-cell", hunk.functionLine ? hunk.functionLine : "\u00a0");
+ hunkCell.colSpan = file.status == Splinter.Patch.CHANGED ? 4 : 1;
+ hunkHeader.appendChild(hunkCell);
+ }
+
+ Splinter.appendPatchHunk(file, hunk, file.status, true, true, tbody);
+ }
+};
+
+Splinter.appendReviewComment = function (comment, parentDiv) {
+ var commentDiv = Splinter.EL("div", "review-patch-comment");
+ Event.addListener(commentDiv, 'click', function() {
+ Splinter.showPatchFile(comment.file.patchFile);
+ if (comment.file.review == Splinter.theReview) {
+ // Immediately start editing the comment again
+ var commentDivParent = Dom.getAncestorByClassName(comment.div, 'comment-area');
+ var commentArea = commentDivParent.getElementsByTagName('td')[0];
+ Splinter.insertCommentEditor(commentArea, comment.file.patchFile, comment.location, comment.type);
+ Splinter.scrollToElement(Dom.get('commentEditor'));
+ } else {
+ // Just scroll to the comment, don't start a reply yet
+ Splinter.scrollToElement(Dom.get(comment.div));
+ }
+ });
+
+ var inReplyTo = comment.getInReplyTo();
+ if (inReplyTo) {
+ var div = new Element(document.createElement('div'));
+ Dom.addClass(div, Splinter.getReviewerClass(inReplyTo.file.review));
+ div.appendTo(commentDiv);
+
+ var reviewerBox = new Element(document.createElement('div'));
+ Dom.addClass(reviewerBox, 'reviewer-box');
+ Splinter.Utils.preWrapLines(reviewerBox, inReplyTo.comment);
+ reviewerBox.appendTo(div);
+
+ var reviewPatchCommentText = new Element(document.createElement('div'));
+ Dom.addClass(reviewPatchCommentText, 'review-patch-comment-text');
+ Splinter.Utils.preWrapLines(reviewPatchCommentText, comment.comment);
+ reviewPatchCommentText.appendTo(commentDiv);
+
+ } else {
+ var hunk = comment.getHunk();
+
+ var lastLine = Math.max(hunk.oldStart + hunk.oldCount- 1,
+ hunk.newStart + hunk.newCount- 1);
+ var tbody = Splinter.appendPatchTable(comment.type, lastLine, commentDiv);
+
+ Splinter.appendPatchHunk(comment.file.patchFile, hunk, comment.type, false, false, tbody,
+ function(loc) {
+ return (loc <= comment.location && comment.location - loc < 5);
+ });
+
+ var tr = new Element(document.createElement('tr'));
+ var td = new Element(document.createElement('td'));
+ td.appendTo(tr);
+ td = new Element(document.createElement('td'));
+ Dom.addClass(td, 'review-patch-comment-text');
+ Splinter.Utils.preWrapLines(td, comment.comment);
+ td.appendTo(tr);
+ tr.appendTo(tbody);
+ }
+
+ parentDiv.appendChild(commentDiv);
+};
+
+Splinter.appendReviewComments = function (review, parentDiv) {
+ var i;
+ for (i = 0; i < review.files.length; i++) {
+ var file = review.files[i];
+
+ if (file.comments.length == 0) {
+ continue;
+ }
+
+ parentDiv.appendChild(Splinter.EL("div", "review-patch-file", file.patchFile.filename));
+ var firstComment = true;
+ var j;
+ for (j = 0; j < file.comments.length; j++) {
+ if (firstComment) {
+ firstComment = false;
+ } else {
+ parentDiv.appendChild(Splinter.EL("div", "review-patch-comment-separator"));
+ }
+
+ Splinter.appendReviewComment(file.comments[j], parentDiv);
+ }
+ }
+};
+
+Splinter.updateMyPatchComments = function () {
+ var myPatchComments = Dom.get("myPatchComments");
+ myPatchComments.innerHTML = '';
+ Splinter.appendReviewComments(Splinter.theReview, myPatchComments);
+ if (Dom.getChildren(myPatchComments).length > 0) {
+ Dom.setStyle(myPatchComments, 'display', 'block');
+ } else {
+ Dom.setStyle(myPatchComments, 'display', 'none');
+ }
+};
+
+Splinter.selectNavigationLink = function (identifier) {
+ var navigationLinks = Dom.getElementsByClassName('navigation-link');
+ var i;
+ for (i = 0; i < navigationLinks.length; i++) {
+ Dom.removeClass(navigationLinks[i], 'navigation-link-selected');
+ }
+ Dom.addClass(Splinter.navigationLinks[identifier], 'navigation-link-selected');
+};
+
+Splinter.addNavigationLink = function (identifier, title, callback, selected) {
+ var navigationDiv = Dom.get('navigation');
+ if (Dom.getChildren(navigationDiv).length > 0) {
+ navigationDiv.appendChild(document.createTextNode(' | '));
+ }
+
+ var navigationLink = new Element(document.createElement('a'));
+ Dom.addClass(navigationLink, 'navigation-link');
+ Dom.setAttribute(navigationLink, 'href', 'javascript:void(0);');
+ Dom.setAttribute(navigationLink, 'id', 'switch-' + encodeURIComponent(identifier));
+ Dom.setAttribute(navigationLink, 'title', identifier);
+ navigationLink.appendChild(document.createTextNode(title));
+ navigationLink.appendTo(navigationDiv);
+
+ // FIXME: Find out why I need to use an id here instead of just passing
+ // navigationLink to Event.addListener()
+ Event.addListener('switch-' + encodeURIComponent(identifier), 'click', function () {
+ if (!Dom.hasClass(this, 'navigation-link-selected')) {
+ callback();
+ }
+ });
+
+ if (selected) {
+ Dom.addClass(navigationLink, 'navigation-link-selected');
+ }
+
+ Splinter.navigationLinks[identifier] = navigationLink;
+};
+
+Splinter.showOverview = function () {
+ Splinter.selectNavigationLink('__OVERVIEW__');
+ Dom.setStyle('overview', 'display', 'block');
+ Dom.getElementsByClassName('file', 'div', '', function (node) {
+ Dom.setStyle(node, 'display', 'none');
+ });
+ Splinter.updateMyPatchComments();
+};
+
+Splinter.showAllFiles = function () {
+ Splinter.selectNavigationLink('__ALL__');
+ Dom.setStyle('overview', 'display', 'none');
+ Dom.setStyle('file-collapse-all', 'display', 'block');
+
+ var i;
+ for (i = 0; i < Splinter.thePatch.files.length; i++) {
+ var file = Splinter.thePatch.files[i];
+ if (!file.div) {
+ Splinter.addPatchFile(file);
+ } else {
+ Dom.setStyle(file.div, 'display', 'block');
+ }
+ }
+}
+
+Splinter.toggleCollapsed = function (filename, display) {
+ filename = decodeURIComponent(filename);
+ var i;
+ for (i = 0; i < Splinter.thePatch.files.length; i++) {
+ var file = Splinter.thePatch.files[i];
+ if (!filename || filename == file.filename) {
+ var fileTableContainer = file.div.getElementsByClassName('file-table-container')[0];
+ var fileCollapseLink = file.div.getElementsByClassName('file-label-collapse')[0];
+ if (!display) {
+ display = Dom.getStyle(fileTableContainer, 'display') == 'block' ? 'none' : 'block';
+ }
+ Dom.setStyle(fileTableContainer, 'display', display);
+ fileCollapseLink.innerHTML = display == 'block' ? '[-]' : '[+]';
+ }
+ }
+}
+
+Splinter.toggleFileReviewed = function (filename) {
+ var checkbox = Dom.get('file-review-checkbox-' + filename);
+ if (checkbox) {
+ filename = decodeURIComponent(filename);
+ for (var i = 0; i < Splinter.thePatch.files.length; i++) {
+ var file = Splinter.thePatch.files[i];
+ if (file.filename == filename) {
+ file.fileReviewed = checkbox.checked;
+
+ Splinter.saveDraft();
+ Splinter.queueUpdateHaveDraft();
+
+ // Strike through file names to show review was completed
+ var fileNavLink = Dom.get('switch-' + encodeURIComponent(filename));
+ if (file.fileReviewed) {
+ Dom.addClass(fileNavLink, 'file-reviewed-nav');
+ }
+ else {
+ Dom.removeClass(fileNavLink, 'file-reviewed-nav');
+ }
+ }
+ }
+ }
+}
+
+Splinter.showPatchFile = function (file) {
+ Splinter.selectNavigationLink(file.filename);
+ Dom.setStyle('overview', 'display', 'none');
+ Dom.setStyle('file-collapse-all', 'display', 'none');
+
+ Dom.getElementsByClassName('file', 'div', '', function (node) {
+ Dom.setStyle(node, 'display', 'none');
+ });
+
+ if (file.div) {
+ Dom.setStyle(file.div, 'display', 'block');
+ } else {
+ Splinter.addPatchFile(file);
+ }
+};
+
+Splinter.addFileNavigationLink = function (file) {
+ var basename = file.filename.replace(/.*\//, "");
+ Splinter.addNavigationLink(file.filename, basename, function() {
+ Splinter.showPatchFile(file);
+ });
+};
+
+Splinter.start = function () {
+ Dom.setStyle('attachmentInfo', 'display', 'block');
+ Dom.setStyle('navigationContainer', 'display', 'block');
+ Dom.setStyle('overview', 'display', 'block');
+ Dom.setStyle('files', 'display', 'block');
+ Dom.setStyle('attachmentStatusSpan', 'display', 'none');
+
+ if (Splinter.thePatch.intro) {
+ Splinter.Utils.preWrapLines(Dom.get('patchIntro'), Splinter.thePatch.intro);
+ } else {
+ Dom.setStyle('patchIntro', 'display', 'none');
+ }
+
+ Splinter.addNavigationLink('__OVERVIEW__', "Overview", Splinter.showOverview, true);
+ Splinter.addNavigationLink('__ALL__', "All Files", Splinter.showAllFiles, false);
+
+ var i;
+ for (i = 0; i < Splinter.thePatch.files.length; i++) {
+ Splinter.addFileNavigationLink(Splinter.thePatch.files[i]);
+ }
+
+ var navigation = Dom.get('navigation');
+
+ var haveDraftNotice = new Element(document.createElement('div'));
+ Dom.setAttribute(haveDraftNotice, 'id', 'haveDraftNotice');
+ haveDraftNotice.appendChild(document.createTextNode('Draft'));
+ haveDraftNotice.appendTo(navigation);
+
+ var clear = new Element(document.createElement('div'));
+ Dom.addClass(clear, 'clear');
+ clear.appendTo(navigation);
+
+ var numReviewers = 0;
+ for (i = 0; i < Splinter.theBug.comments.length; i++) {
+ var comment = Splinter.theBug.comments[i];
+ var m = Splinter.Review.REVIEW_RE.exec(comment.text);
+
+ if (m && parseInt(m[1], 10) == Splinter.attachmentId) {
+ var review = new Splinter.Review.Review(Splinter.thePatch, comment.getWho(), comment.date);
+ review.parse(comment.text.substr(m[0].length));
+
+ var reviewerIndex;
+ if (review.who in Splinter.reviewers) {
+ reviewerIndex = Splinter.reviewers[review.who];
+ } else {
+ reviewerIndex = ++numReviewers;
+ Splinter.reviewers[review.who] = reviewerIndex;
+ }
+
+ var reviewDiv = new Element(document.createElement('div'));
+ Dom.addClass(reviewDiv, 'review');
+ Dom.addClass(reviewDiv, Splinter.getReviewerClass(review));
+ reviewDiv.appendTo(Dom.get('oldReviews'));
+
+ var reviewerBox = new Element(document.createElement('div'));
+ Dom.addClass(reviewerBox, 'reviewer-box');
+ reviewerBox.appendTo(reviewDiv);
+
+ var reviewer = new Element(document.createElement('div'));
+ Dom.addClass(reviewer, 'reviewer');
+ reviewer.appendChild(document.createTextNode(review.who));
+ reviewer.appendTo(reviewerBox);
+
+ var reviewDate = new Element(document.createElement('div'));
+ Dom.addClass(reviewDate, 'review-date');
+ reviewDate.appendChild(document.createTextNode(Splinter.Utils.formatDate(review.date)));
+ reviewDate.appendTo(reviewerBox);
+
+ var reviewInfoBottom = new Element(document.createElement('div'));
+ Dom.addClass(reviewInfoBottom, 'review-info-bottom');
+ reviewInfoBottom.appendTo(reviewerBox);
+
+ var reviewIntro = new Element(document.createElement('div'));
+ Dom.addClass(reviewIntro, 'review-intro');
+ Splinter.Utils.preWrapLines(reviewIntro, review.intro? review.intro : "");
+ reviewIntro.appendTo(reviewerBox);
+
+ Dom.setStyle('oldReviews', 'display', 'block');
+
+ Splinter.appendReviewComments(review, reviewerBox);
+ }
+ }
+
+ // We load the saved draft or create a new review *after* inserting the existing reviews
+ // so that the ordering comes out right.
+
+ if (Splinter.reviewStorage) {
+ Splinter.theReview = Splinter.reviewStorage.loadDraft(Splinter.theBug, Splinter.theAttachment, Splinter.thePatch);
+ if (Splinter.theReview) {
+ var storedReviews = Splinter.reviewStorage.listReviews();
+ Dom.setStyle('restored', 'display', 'block');
+ for (i = 0; i < storedReviews.length; i++) {
+ if (storedReviews[i].bugId == Splinter.theBug.id &&
+ storedReviews[i].attachmentId == Splinter.theAttachment.id)
+ {
+ Dom.get("restoredLastModified").innerHTML = Splinter.Utils.formatDate(new Date(storedReviews[i].modificationTime));
+ // Restore file reviewed checkboxes
+ if (storedReviews[i].filesReviewed) {
+ for (var j = 0; j < Splinter.thePatch.files.length; j++) {
+ var file = Splinter.thePatch.files[j];
+ if (storedReviews[i].filesReviewed[file.filename]) {
+ file.fileReviewed = true;
+ // Strike through file names to show that review was completed
+ var fileNavLink = Dom.get('switch-' + encodeURIComponent(file.filename));
+ Dom.addClass(fileNavLink, 'file-reviewed-nav');
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!Splinter.theReview) {
+ Splinter.theReview = new Splinter.Review.Review(Splinter.thePatch);
+ }
+
+ if (Splinter.theReview.intro) {
+ Dom.setStyle('emptyCommentNotice', 'display', 'none');
+ }
+
+ var myComment = Dom.get('myComment');
+ myComment.value = Splinter.theReview.intro ? Splinter.theReview.intro : "";
+ Event.addListener(myComment, 'focus', function () {
+ Dom.setStyle('emptyCommentNotice', 'display', 'none');
+ });
+ Event.addListener(myComment, 'blur', function () {
+ if (myComment.value == '') {
+ Dom.setStyle('emptyCommentNotice', 'display', 'block');
+ }
+ });
+ Event.addListener(myComment, 'keydown', function () {
+ Splinter.queueSaveDraft();
+ Splinter.queueUpdateHaveDraft();
+ });
+
+ Splinter.updateMyPatchComments();
+
+ Splinter.queueUpdateHaveDraft();
+
+ Event.addListener("publishButton", "click", Splinter.publishReview);
+ Event.addListener("cancelButton", "click", Splinter.discardReview);
+};
+
+Splinter.newPageUrl = function (newBugId, newAttachmentId) {
+ var newUrl = Splinter.configBase;
+ if (newBugId != null) {
+ newUrl += (newUrl.indexOf("?") < 0) ? "?" : "&";
+ newUrl += "bug=" + escape("" + newBugId);
+ if (newAttachmentId != null) {
+ newUrl += "&attachment=" + escape("" + newAttachmentId);
+ }
+ }
+
+ return newUrl;
+};
+
+Splinter.showNote = function () {
+ var noteDiv = Dom.get("note");
+ if (noteDiv && Splinter.configNote) {
+ noteDiv.innerHTML = Splinter.configNote;
+ Dom.setStyle(noteDiv, 'display', 'block');
+ }
+};
+
+Splinter.showEnterBug = function () {
+ Splinter.showNote();
+
+ Event.addListener("enterBugGo", "click", function () {
+ var newBugId = Splinter.Utils.strip(Dom.get("enterBugInput").value);
+ document.location = Splinter.newPageUrl(newBugId);
+ });
+
+ Dom.setStyle('enterBug', 'display', 'block');
+
+ if (!Splinter.reviewStorage) {
+ return;
+ }
+
+ var storedReviews = Splinter.reviewStorage.listReviews();
+ if (storedReviews.length == 0) {
+ return;
+ }
+
+ var i;
+ var reviewData = [];
+ for (i = storedReviews.length - 1; i >= 0; i--) {
+ var reviewInfo = storedReviews[i];
+ var modificationDate = Splinter.Utils.formatDate(new Date(reviewInfo.modificationTime));
+ var extra = reviewInfo.isDraft ? "(draft)" : "";
+
+ reviewData.push([
+ reviewInfo.bugId,
+ reviewInfo.bugId + ":" + reviewInfo.attachmentId + ":" + reviewInfo.attachmentDescription,
+ modificationDate,
+ extra
+ ]);
+ }
+
+ var attachLink = function (elLiner, oRecord, oColumn, oData) {
+ var splitResult = oData.split(':', 3);
+ elLiner.innerHTML = "<a href=\"" + Splinter.newPageUrl(splitResult[0], splitResult[1]) +
+ "\">" + splitResult[1] + " - " + splitResult[2] + "</a>";
+ };
+
+ var bugLink = function (elLiner, oRecord, oColumn, oData) {
+ elLiner.innerHTML = "<a href=\"" + Splinter.newPageUrl(oData) +
+ "\">" + oData + "</a>";
+ };
+
+ dsConfig = {
+ responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
+ responseSchema: { fields:["bug_id","attachment", "date", "extra"] }
+ };
+
+ var columnDefs = [
+ { key: "bug_id", label: "Bug", formatter: bugLink },
+ { key: "attachment", label: "Attachment", formatter: attachLink },
+ { key: "date", label: "Date" },
+ { key: "extra", label: "Extra" }
+ ];
+
+ var dataSource = new YAHOO.util.LocalDataSource(reviewData, dsConfig);
+ var dataTable = new YAHOO.widget.DataTable("chooseReviewTable", columnDefs, dataSource);
+
+ Dom.setStyle('chooseReview', 'display', 'block');
+};
+
+Splinter.showChooseAttachment = function () {
+ var drafts = {};
+ var published = {};
+ if (Splinter.reviewStorage) {
+ var storedReviews = Splinter.reviewStorage.listReviews();
+ var j;
+ for (j = 0; j < storedReviews.length; j++) {
+ var reviewInfo = storedReviews[j];
+ if (reviewInfo.bugId == Splinter.theBug.id) {
+ if (reviewInfo.isDraft) {
+ drafts[reviewInfo.attachmentId] = 1;
+ } else {
+ published[reviewInfo.attachmentId] = 1;
+ }
+ }
+ }
+ }
+
+ var attachData = [];
+
+ var i;
+ for (i = 0; i < Splinter.theBug.attachments.length; i++) {
+ var attachment = Splinter.theBug.attachments[i];
+
+ if (!attachment.isPatch || attachment.isObsolete) {
+ continue;
+ }
+
+ var href = Splinter.newPageUrl(Splinter.theBug.id, attachment.id);
+
+ var date = Splinter.Utils.formatDate(attachment.date);
+ var status = (attachment.status && attachment.status != 'none') ? attachment.status : '';
+
+ var extra = '';
+ if (attachment.id in drafts) {
+ extra = '(draft)';
+ } else if (attachment.id in published) {
+ extra = '(published)';
+ }
+
+ attachData.push([ attachment.id, attachment.description, attachment.date, extra ]);
+ }
+
+ var attachLink = function (elLiner, oRecord, oColumn, oData) {
+ elLiner.innerHTML = "<a href=\"" + Splinter.newPageUrl(Splinter.theBug.id, oData) +
+ "\">" + oData + "</a>";
+ };
+
+ dsConfig = {
+ responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
+ responseSchema: { fields:["id","description","date", "extra"] }
+ };
+
+ var columnDefs = [
+ { key: "id", label: "ID", formatter: attachLink },
+ { key: "description", label: "Description" },
+ { key: "date", label: "Date" },
+ { key: "extra", label: "Extra" }
+ ];
+
+ var dataSource = new YAHOO.util.LocalDataSource(attachData, dsConfig);
+ var dataTable = new YAHOO.widget.DataTable("chooseAttachmentTable", columnDefs, dataSource);
+
+ Dom.setStyle('chooseAttachment', 'display', 'block');
+};
+
+Splinter.quickHelpToggle = function () {
+ var quickHelpShow = Dom.get('quickHelpShow');
+ var quickHelpContent = Dom.get('quickHelpContent');
+ var quickHelpToggle = Dom.get('quickHelpToggle');
+
+ if (quickHelpContent.style.display == 'none') {
+ quickHelpContent.style.display = 'block';
+ quickHelpShow.style.display = 'none';
+ } else {
+ quickHelpContent.style.display = 'none';
+ quickHelpShow.style.display = 'block';
+ }
+};
+
+Splinter.init = function () {
+ Splinter.showNote();
+
+ if (Splinter.ReviewStorage.LocalReviewStorage.available()) {
+ Splinter.reviewStorage = new Splinter.ReviewStorage.LocalReviewStorage();
+ }
+
+ if (Splinter.theBug == null) {
+ Splinter.showEnterBug();
+ return;
+ }
+
+ Dom.get("bugId").innerHTML = Splinter.theBug.id;
+ Dom.get("bugLink").setAttribute('href', Splinter.configBugUrl + "show_bug.cgi?id=" + Splinter.theBug.id);
+ Dom.get("bugShortDesc").innerHTML = YAHOO.lang.escapeHTML(Splinter.theBug.shortDesc);
+ Dom.get("bugReporter").appendChild(document.createTextNode(Splinter.theBug.getReporter()));
+ Dom.get("bugCreationDate").innerHTML = Splinter.Utils.formatDate(Splinter.theBug.creationDate);
+ Dom.setStyle('bugInfo', 'display', 'block');
+
+ if (Splinter.attachmentId) {
+ Splinter.theAttachment = Splinter.theBug.getAttachment(Splinter.attachmentId);
+
+ if (Splinter.theAttachment == null) {
+ Splinter.displayError("Attachment " + Splinter.attachmentId + " is not an attachment to bug " + Splinter.theBug.id);
+ }
+ else if (!Splinter.theAttachment.isPatch) {
+ Splinter.displayError("Attachment " + Splinter.attachmentId + " is not a patch");
+ Splinter.theAttachment = null;
+ }
+ }
+
+ if (Splinter.theAttachment == null) {
+ Splinter.showChooseAttachment();
+
+ } else {
+ Dom.get("attachId").innerHTML = Splinter.theAttachment.id;
+ Dom.get("attachLink").setAttribute('href', Splinter.configBugUrl + "attachment.cgi?id=" + Splinter.theAttachment.id);
+ Dom.get("attachDesc").innerHTML = YAHOO.lang.escapeHTML(Splinter.theAttachment.description);
+ Dom.get("attachCreator").appendChild(document.createTextNode(Splinter.Bug._formatWho(Splinter.theAttachment.whoName,
+ Splinter.theAttachment.whoEmail)));
+ Dom.get("attachDate").innerHTML = Splinter.Utils.formatDate(Splinter.theAttachment.date);
+ if (Splinter.theAttachment.isObsolete) {
+ Dom.get("attachObsolete").innerHTML = 'OBSOLETE';
+ }
+ Dom.setStyle('attachInfo', 'display', 'block');
+
+ Dom.setStyle('quickHelpShow', 'display', 'block');
+
+ document.title = "Patch Review of Attachment " + Splinter.theAttachment.id +
+ " for Bug " + Splinter.theBug.id;
+
+ Splinter.thePatch = new Splinter.Patch.Patch(Splinter.theAttachment.data);
+ if (Splinter.thePatch != null) {
+ Splinter.start();
+ }
+ }
+};
+
+YAHOO.util.Event.addListener(window, 'load', Splinter.init);
diff --git a/extensions/TagNewUsers/Config.pm b/extensions/TagNewUsers/Config.pm
new file mode 100644
index 000000000..c2330afc8
--- /dev/null
+++ b/extensions/TagNewUsers/Config.pm
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TagNewUsers;
+use strict;
+
+use constant NAME => 'TagNewUsers';
+use constant REQUIRED_MODULES => [ ];
+use constant OPTIONAL_MODULES => [ ];
+
+__PACKAGE__->NAME;
diff --git a/extensions/TagNewUsers/Extension.pm b/extensions/TagNewUsers/Extension.pm
new file mode 100644
index 000000000..13a517406
--- /dev/null
+++ b/extensions/TagNewUsers/Extension.pm
@@ -0,0 +1,258 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TagNewUsers;
+use strict;
+use base qw(Bugzilla::Extension);
+use Bugzilla::Field;
+use Bugzilla::User;
+use Bugzilla::Install::Util qw(indicate_progress);
+use Date::Parse;
+use Scalar::Util qw(blessed);
+
+# users younger than PROFILE_AGE days will be tagged as new
+use constant PROFILE_AGE => 60;
+
+# users with fewer comments than COMMENT_COUNT will be tagged as new
+use constant COMMENT_COUNT => 25;
+
+our $VERSION = '1';
+
+#
+# install
+#
+
+sub install_update_db {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ if (!$dbh->bz_column_info('profiles', 'comment_count')) {
+ $dbh->bz_add_column('profiles', 'comment_count',
+ {TYPE => 'INT3', NOTNULL => 1, DEFAULT => 0});
+ my $sth = $dbh->prepare('UPDATE profiles SET comment_count=? WHERE userid=?');
+ my $ra = $dbh->selectall_arrayref('SELECT who,COUNT(*) FROM longdescs GROUP BY who');
+ my $count = 1;
+ my $total = scalar @$ra;
+ foreach my $ra_row (@$ra) {
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ my ($user_id, $count) = @$ra_row;
+ $sth->execute($count, $user_id);
+ }
+ }
+
+ if (!$dbh->bz_column_info('profiles', 'creation_ts')) {
+ $dbh->bz_add_column('profiles', 'creation_ts',
+ {TYPE => 'DATETIME'});
+ my $creation_date_fieldid = get_field_id('creation_ts');
+ my $sth = $dbh->prepare('UPDATE profiles SET creation_ts=? WHERE userid=?');
+ my $ra = $dbh->selectall_arrayref("
+ SELECT p.userid, a.profiles_when
+ FROM profiles p
+ LEFT JOIN profiles_activity a ON a.userid=p.userid
+ AND a.fieldid=$creation_date_fieldid
+ ");
+ my ($now) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
+ my $count = 1;
+ my $total = scalar @$ra;
+ foreach my $ra_row (@$ra) {
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ my ($user_id, $when) = @$ra_row;
+ if (!$when) {
+ ($when) = $dbh->selectrow_array(
+ "SELECT bug_when FROM bugs_activity WHERE who=? ORDER BY bug_when " .
+ $dbh->sql_limit(1),
+ undef, $user_id
+ );
+ }
+ if (!$when) {
+ ($when) = $dbh->selectrow_array(
+ "SELECT bug_when FROM longdescs WHERE who=? ORDER BY bug_when " .
+ $dbh->sql_limit(1),
+ undef, $user_id
+ );
+ }
+ if (!$when) {
+ ($when) = $dbh->selectrow_array(
+ "SELECT creation_ts FROM bugs WHERE reporter=? ORDER BY creation_ts " .
+ $dbh->sql_limit(1),
+ undef, $user_id
+ );
+ }
+ if (!$when) {
+ $when = $now;
+ }
+
+ $sth->execute($when, $user_id);
+ }
+ }
+
+ if (!$dbh->bz_column_info('profiles', 'first_patch_bug_id')) {
+ $dbh->bz_add_column('profiles', 'first_patch_bug_id', {TYPE => 'INT3'});
+ my $sth_update = $dbh->prepare('UPDATE profiles SET first_patch_bug_id=? WHERE userid=?');
+ my $sth_select = $dbh->prepare(
+ 'SELECT bug_id FROM attachments WHERE submitter_id=? AND ispatch=1 ORDER BY creation_ts ' . $dbh->sql_limit(1)
+ );
+ my $ra = $dbh->selectcol_arrayref('SELECT DISTINCT submitter_id FROM attachments WHERE ispatch=1');
+ my $count = 1;
+ my $total = scalar @$ra;
+ foreach my $user_id (@$ra) {
+ indicate_progress({ current => $count++, total => $total, every => 25 });
+ $sth_select->execute($user_id);
+ my ($bug_id) = $sth_select->fetchrow_array;
+ $sth_update->execute($bug_id, $user_id);
+ }
+ }
+}
+
+#
+# objects
+#
+
+sub object_columns {
+ my ($self, $args) = @_;
+ my ($class, $columns) = @$args{qw(class columns)};
+ if ($class->isa('Bugzilla::User')) {
+ push(@$columns, qw(comment_count creation_ts first_patch_bug_id));
+ }
+}
+
+sub object_before_create {
+ my ($self, $args) = @_;
+ my ($class, $params) = @$args{qw(class params)};
+ if ($class->isa('Bugzilla::User')) {
+ my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
+ $params->{comment_count} = 0;
+ $params->{creation_ts} = $timestamp;
+ } elsif ($class->isa('Bugzilla::Attachment')) {
+ if ($params->{ispatch} && !Bugzilla->user->first_patch_bug_id) {
+ Bugzilla->user->first_patch_bug_id($params->{bug}->id);
+ }
+ }
+}
+
+#
+# Bugzilla::User methods
+#
+
+BEGIN {
+ *Bugzilla::User::comment_count = \&_comment_count;
+ *Bugzilla::User::creation_ts = \&_creation_ts;
+ *Bugzilla::User::update_comment_count = \&_update_comment_count;
+ *Bugzilla::User::first_patch_bug_id = \&_first_patch_bug_id;
+ *Bugzilla::User::is_new = \&_is_new;
+ *Bugzilla::User::creation_age = \&_creation_age;
+}
+
+sub _comment_count { return $_[0]->{comment_count} }
+sub _creation_ts { return $_[0]->{creation_ts} }
+
+sub _update_comment_count {
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
+
+ # no need to update this counter for users which are no longer new
+ return unless $self->is_new;
+
+ my $id = $self->id;
+ my ($count) = $dbh->selectrow_array(
+ "SELECT COUNT(*) FROM longdescs WHERE who=?",
+ undef, $id
+ );
+ return if $self->{comment_count} == $count;
+ $dbh->do(
+ 'UPDATE profiles SET comment_count=? WHERE userid=?',
+ undef, $count, $id
+ );
+ $self->{comment_count} = $count;
+}
+
+sub _first_patch_bug_id {
+ my ($self, $bug_id) = @_;
+ return $self->{first_patch_bug_id} unless defined $bug_id;
+
+ Bugzilla->dbh->do(
+ 'UPDATE profiles SET first_patch_bug_id=? WHERE userid=?',
+ undef, $bug_id, $self->id
+ );
+ $self->{first_patch_bug_id} = $bug_id;
+}
+
+sub _is_new {
+ my ($self) = @_;
+
+ if (!exists $self->{is_new}) {
+ if ($self->in_group('canconfirm')) {
+ $self->{is_new} = 0;
+ } else {
+ $self->{is_new} = ($self->comment_count <= COMMENT_COUNT)
+ || ($self->creation_age <= PROFILE_AGE);
+ }
+ }
+
+ return $self->{is_new};
+}
+
+sub _creation_age {
+ my ($self) = @_;
+
+ if (!exists $self->{creation_age}) {
+ my $age = sprintf("%.0f", (time() - str2time($self->creation_ts)) / 86400);
+ $self->{creation_age} = $age;
+ }
+
+ return $self->{creation_age};
+}
+
+#
+# hooks
+#
+
+sub bug_end_of_create {
+ Bugzilla->user->update_comment_count();
+}
+
+sub bug_end_of_update {
+ Bugzilla->user->update_comment_count();
+}
+
+sub mailer_before_send {
+ my ($self, $args) = @_;
+ my $email = $args->{email};
+
+ my ($bug_id) = ($email->header('Subject') =~ /^[^\d]+(\d+)/);
+ my $changer_login = $email->header('X-Bugzilla-Who');
+ my $changed_fields = $email->header('X-Bugzilla-Changed-Fields');
+
+ if ($bug_id
+ && $changer_login
+ && $changed_fields =~ /attachments.created/)
+ {
+ my $changer = Bugzilla::User->new({ name => $changer_login });
+ if ($changer
+ && $changer->first_patch_bug_id
+ && $changer->first_patch_bug_id == $bug_id)
+ {
+ $email->header_set('X-Bugzilla-FirstPatch' => $bug_id);
+ }
+ }
+}
+
+sub webservice_user_get {
+ my ($self, $args) = @_;
+ my ($webservice, $params, $users) = @$args{qw(webservice params users)};
+
+ foreach my $user (@$users) {
+ # Most of the time the hash values are XMLRPC::Data objects
+ my $email = blessed $user->{'email'} ? $user->{'email'}->value : $user->{'email'};
+ if ($email) {
+ my $user_obj = Bugzilla::User->new({ name => $email });
+ $user->{'is_new'} = $webservice->type('boolean', $user_obj->is_new ? 1 : 0);
+ }
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/TagNewUsers/template/en/default/hook/bug/comments-user.html.tmpl b/extensions/TagNewUsers/template/en/default/hook/bug/comments-user.html.tmpl
new file mode 100644
index 000000000..81cfc776a
--- /dev/null
+++ b/extensions/TagNewUsers/template/en/default/hook/bug/comments-user.html.tmpl
@@ -0,0 +1,26 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% RETURN UNLESS user.in_group('canconfirm') %]
+[% IF comment.author.is_new %]
+<span class="new_user" title="
+[%- comment.author.comment_count FILTER html %] comment[% "s" IF comment.author.comment_count != 1 -%]
+, created [%
+IF comment.author.creation_age == 0 %]today[%
+ELSIF comment.author.creation_age > 365 %]more than a year ago[%
+ELSE %][% comment.author.creation_age FILTER html %] day[% "s" IF comment.author.creation_age != 1 %] ago[% END %]."
+ >
+(New to [% terms.Bugzilla %])
+</span>
+[% END %]
+[% IF comment.is_about_attachment
+ && comment.author.first_patch_bug_id == bug.id
+ && comment.attachment.ispatch
+%]
+<span class="new_user">(First Patch)</span>
+[% END %]
diff --git a/extensions/TagNewUsers/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/TagNewUsers/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..bff73e963
--- /dev/null
+++ b/extensions/TagNewUsers/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,9 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% style_urls.push('extensions/TagNewUsers/web/style.css') IF user.in_group('canconfirm') %]
diff --git a/extensions/TagNewUsers/web/style.css b/extensions/TagNewUsers/web/style.css
new file mode 100644
index 000000000..842dca02e
--- /dev/null
+++ b/extensions/TagNewUsers/web/style.css
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+.new_user {
+ color: #448844;
+}
diff --git a/extensions/TryAutoLand/Config.pm b/extensions/TryAutoLand/Config.pm
new file mode 100644
index 000000000..8b299183b
--- /dev/null
+++ b/extensions/TryAutoLand/Config.pm
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TryAutoLand;
+use strict;
+
+use constant NAME => 'TryAutoLand';
+
+use constant REQUIRED_MODULES => [
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/TryAutoLand/Extension.pm b/extensions/TryAutoLand/Extension.pm
new file mode 100644
index 000000000..40dbb70d9
--- /dev/null
+++ b/extensions/TryAutoLand/Extension.pm
@@ -0,0 +1,323 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TryAutoLand;
+
+use strict;
+
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Bug;
+use Bugzilla::Attachment;
+use Bugzilla::User;
+use Bugzilla::Util qw(trick_taint diff_arrays);
+use Bugzilla::Error;
+
+use Bugzilla::Extension::TryAutoLand::Constants;
+
+our $VERSION = '0.01';
+
+BEGIN {
+ *Bugzilla::Bug::autoland_branches = \&_autoland_branches;
+ *Bugzilla::Bug::autoland_try_syntax = \&_autoland_try_syntax;
+ *Bugzilla::Attachment::autoland_checked = \&_autoland_attachment_checked;
+ *Bugzilla::Attachment::autoland_who = \&_autoland_attachment_who;
+ *Bugzilla::Attachment::autoland_status = \&_autoland_attachment_status;
+ *Bugzilla::Attachment::autoland_status_when = \&_autoland_attachment_status_when;
+ *Bugzilla::Attachment::autoland_update_status = \&_autoland_attachment_update_status;
+ *Bugzilla::Attachment::autoland_remove = \&_autoland_attachment_remove;
+}
+
+sub db_schema_abstract_schema {
+ my ($self, $args) = @_;
+ $args->{'schema'}->{'autoland_branches'} = {
+ FIELDS => [
+ bug_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ REFERENCES => {
+ TABLE => 'bugs',
+ COLUMN => 'bug_id',
+ DELETE => 'CASCADE'
+ }
+ },
+ branches => {
+ TYPE => 'VARCHAR(255)',
+ NOTNULL => 1
+ },
+ try_syntax => {
+ TYPE => 'VARCHAR(255)',
+ NOTNULL => 1,
+ DEFAULT => "''",
+ }
+ ],
+ };
+
+ $args->{'schema'}->{'autoland_attachments'} = {
+ FIELDS => [
+ attach_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ PRIMARYKEY => 1,
+ REFERENCES => {
+ TABLE => 'attachments',
+ COLUMN => 'attach_id',
+ DELETE => 'CASCADE'
+ },
+ },
+ who => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ REFERENCES => {
+ TABLE => 'profiles',
+ COLUMN => 'userid',
+ },
+ },
+ status => {
+ TYPE => 'varchar(64)',
+ NOTNULL => 1
+ },
+ status_when => {
+ TYPE => 'DATETIME',
+ NOTNULL => 1,
+ },
+ ],
+ };
+}
+
+sub install_update_db {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ if (!$dbh->bz_column_info('autoland_branches', 'try_syntax')) {
+ $dbh->bz_add_column('autoland_branches', 'try_syntax', {
+ TYPE => 'VARCHAR(255)',
+ NOTNULL => 1,
+ DEFAULT => "''",
+ });
+ }
+}
+
+sub _autoland_branches {
+ my $self = shift;
+ return $self->{'autoland_branches'} if exists $self->{'autoland_branches'};
+ _preload_bug_data($self);
+ return $self->{'autoland_branches'};
+}
+
+sub _autoland_try_syntax {
+ my $self = shift;
+ return $self->{'autoland_try_syntax'} if exists $self->{'autoland_try_syntax'};
+ _preload_bug_data($self);
+ return $self->{'autoland_try_syntax'};
+}
+
+sub _preload_bug_data {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $result = $dbh->selectrow_hashref("SELECT branches, try_syntax FROM autoland_branches
+ WHERE bug_id = ?", { Slice => {} }, $self->id);
+ if ($result) {
+ $self->{'autoland_branches'} = $result->{'branches'};
+ $self->{'autoland_try_syntax'} = $result->{'try_syntax'};
+ }
+ else {
+ $self->{'autoland_branches'} = undef;
+ $self->{'autoland_try_syntax'} = undef;
+ }
+}
+
+sub _autoland_attachment_checked {
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
+ return $self->{'autoland_checked'} if exists $self->{'autoland_checked'};
+ my $result = $dbh->selectrow_hashref("SELECT who, status, status_when
+ FROM autoland_attachments
+ WHERE attach_id = ?", { Slice => {} }, $self->id);
+ if ($result) {
+ $self->{'autoland_checked'} = 1;
+ $self->{'autoland_who'} = Bugzilla::User->new($result->{'who'});
+ $self->{'autoland_status'} = $result->{'status'};
+ $self->{'autoland_status_when'} = $result->{'status_when'};
+ }
+ else {
+ $self->{'autoland_checked'} = 0;
+ $self->{'autoland_who'} = undef;
+ $self->{'autoland_status'} = undef;
+ $self->{'autoland_status_when'} = undef;
+ }
+ return $self->{'autoland_checked'};
+}
+
+sub _autoland_attachment_who {
+ my $self = shift;
+ return undef if !$self->autoland_checked;
+ return $self->{'autoland_who'};
+}
+
+sub _autoland_attachment_status {
+ my $self = shift;
+ return undef if !$self->autoland_checked;
+ return $self->{'autoland_status'};
+}
+
+sub _autoland_attachment_status_when {
+ my $self = shift;
+ return undef if !$self->autoland_checked;
+ return $self->{'autoland_status_when'};
+}
+
+sub _autoland_attachment_update_status {
+ my ($self, $status) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return undef if !$self->autoland_checked;
+
+ grep($_ eq $status, VALID_STATUSES)
+ || ThrowUserError('autoland_invalid_status',
+ { status => $status,
+ valid => [ VALID_STATUSES ] });
+
+ if ($self->autoland_status ne $status) {
+ my $timestamp = $dbh->selectrow_array("SELECT LOCALTIMESTAMP(0)");
+ trick_taint($status);
+ $dbh->do("UPDATE autoland_attachments SET status = ?, status_when = ?
+ WHERE attach_id = ?", undef, $status, $timestamp, $self->id);
+ $self->{'autoland_status'} = $status;
+ $self->{'autoland_status_when'} = $timestamp;
+ }
+
+ return 1;
+}
+
+sub _autoland_attachment_remove {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return undef if !$self->autoland_checked;
+ $dbh->do("DELETE FROM autoland_attachments WHERE attach_id = ?", undef, $self->id);
+ delete $self->{'autoland_checked'};
+ delete $self->{'autoland_who'};
+ delete $self->{'autoland_status'};
+ delete $self->{'autoland_status_when'};
+}
+
+sub object_end_of_update {
+ my ($self, $args) = @_;
+ my $object = $args->{'object'};
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->dbh;
+ my $cgi = Bugzilla->cgi;
+ my $params = Bugzilla->input_params;
+
+ return if !$user->in_group('autoland');
+
+ if ($object->isa('Bugzilla::Bug')) {
+ # First make any needed changes to the branches and try_syntax fields
+ my $bug_id = $object->bug_id;
+ my $bug_result = $dbh->selectrow_hashref("SELECT branches, try_syntax
+ FROM autoland_branches
+ WHERE bug_id = ?",
+ { Slice => {} }, $bug_id);
+
+ my $old_branches = '';
+ my $old_try_syntax = '';
+ if ($bug_result) {
+ $old_branches = $bug_result->{'branches'};
+ $old_try_syntax = $bug_result->{'try_syntax'};
+ }
+
+ my $new_branches = $params->{'autoland_branches'} || '';
+ my $new_try_syntax = $params->{'autoland_try_syntax'} || '';
+
+ my $set_attachments = [];
+ if (ref $params->{'autoland_attachments'}) {
+ $set_attachments = $params->{'autoland_attachments'};
+ } elsif ($params->{'autoland_attachments'}) {
+ $set_attachments = [ $params->{'autoland_attachments'} ];
+ }
+
+ # Check for required values
+ (!$new_branches && @{$set_attachments})
+ && ThrowUserError('autoland_empty_branches');
+ ($new_branches && !$new_try_syntax)
+ && ThrowUserError('autoland_empty_try_syntax');
+
+ trick_taint($new_branches);
+ if (!$new_branches && $old_branches) {
+ $dbh->do("DELETE FROM autoland_branches WHERE bug_id = ?",
+ undef, $bug_id);
+ }
+ elsif ($new_branches && !$old_branches) {
+ $dbh->do("INSERT INTO autoland_branches (bug_id, branches)
+ VALUES (?, ?)", undef, $bug_id, $new_branches);
+ }
+ elsif ($old_branches ne $new_branches) {
+ $dbh->do("UPDATE autoland_branches SET branches = ? WHERE bug_id = ?",
+ undef, $new_branches, $bug_id);
+ }
+
+ trick_taint($new_try_syntax);
+ if (($old_try_syntax ne $new_try_syntax) && $new_branches) {
+ $dbh->do("UPDATE autoland_branches SET try_syntax = ? WHERE bug_id = ?",
+ undef, $new_try_syntax, $bug_id);
+ }
+
+ # Next make any changes needed to each of the attachments.
+ # 1. If an attachment is checked it has a row in the table, if
+ # there is no row in the table it is not checked.
+ # 2. Do not allow changes to checked state if status == 'running' or status == 'waiting'
+ my $check_attachments = ref $params->{'defined_autoland_attachments'}
+ ? $params->{'defined_autoland_attachments'}
+ : [ $params->{'defined_autoland_attachments'} ];
+ my ($removed_attachments) = diff_arrays($check_attachments, $set_attachments);
+ foreach my $attachment (@{$object->attachments}) {
+ next if !$attachment->ispatch;
+ my $attach_id = $attachment->id;
+
+ my $checked = (grep $_ == $attach_id, @$set_attachments) ? 1 : 0;
+ my $unchecked = (grep $_ == $attach_id, @$removed_attachments) ? 1 : 0;
+ my $old_checked = $dbh->selectrow_array("SELECT 1 FROM autoland_attachments
+ WHERE attach_id = ?", undef, $attach_id) || 0;
+
+ next if $checked && $old_checked;
+
+ if ($unchecked && $old_checked && $attachment->autoland_status =~ /^(failed|success)$/) {
+ $dbh->do("DELETE FROM autoland_attachments WHERE attach_id = ?", undef, $attach_id);
+ }
+ elsif ($checked && !$old_checked) {
+ $dbh->do("INSERT INTO autoland_attachments (attach_id, who, status, status_when)
+ VALUES (?, ?, 'waiting', now())", undef, $attach_id, $user->id);
+ }
+ }
+
+ }
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ my $vars = $args->{'vars'};
+
+ # in the header we just need to set the var to ensure the css gets included
+ if ($file eq 'bug/show-header.html.tmpl' && Bugzilla->user->in_group('autoland') ) {
+ $vars->{'autoland'} = 1;
+ }
+
+ if ($file eq 'bug/edit.html.tmpl') {
+ $vars->{'autoland_default_try_syntax'} = DEFAULT_TRY_SYNTAX;
+ }
+}
+
+sub webservice {
+ my ($self, $args) = @_;
+
+ my $dispatch = $args->{dispatch};
+ $dispatch->{TryAutoLand} = "Bugzilla::Extension::TryAutoLand::WebService";
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/TryAutoLand/bin/TryAutoLand.getBugs.pl b/extensions/TryAutoLand/bin/TryAutoLand.getBugs.pl
new file mode 100755
index 000000000..5d05831a8
--- /dev/null
+++ b/extensions/TryAutoLand/bin/TryAutoLand.getBugs.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/perl -w
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use XMLRPC::Lite;
+use Data::Dumper;
+use HTTP::Cookies;
+
+###################################
+# Need to login first #
+###################################
+
+my $username = shift;
+my $password = shift;
+
+my $cookie_jar = new HTTP::Cookies( file => "/tmp/lwp_cookies.dat" );
+
+my $rpc = new XMLRPC::Lite;
+
+$rpc->proxy('http://fedora/726193/xmlrpc.cgi');
+
+$rpc->encoding('UTF-8');
+
+$rpc->transport->cookie_jar($cookie_jar);
+
+my $call = $rpc->call( 'User.login',
+ { login => $username, password => $password } );
+
+if ( $call->faultstring ) {
+ print $call->faultstring . "\n";
+ exit;
+}
+
+# Save the cookies in the cookie file
+$rpc->transport->cookie_jar->extract_cookies(
+ $rpc->transport->http_response );
+$rpc->transport->cookie_jar->save;
+
+print "Successfully logged in.\n";
+
+###################################
+# Main call here #
+###################################
+
+$call = $rpc->call('TryAutoLand.getBugs', { status => [] });
+
+my $result = "";
+if ( $call->faultstring ) {
+ print $call->faultstring . "\n";
+ exit;
+}
+else {
+ $result = $call->result;
+}
+
+print Dumper($result);
diff --git a/extensions/TryAutoLand/bin/TryAutoLand.updateStatus.pl b/extensions/TryAutoLand/bin/TryAutoLand.updateStatus.pl
new file mode 100755
index 000000000..4a8f92089
--- /dev/null
+++ b/extensions/TryAutoLand/bin/TryAutoLand.updateStatus.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl -w
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use XMLRPC::Lite;
+use Data::Dumper;
+use HTTP::Cookies;
+
+###################################
+# Need to login first #
+###################################
+
+my $username = shift;
+my $password = shift;
+
+my $cookie_jar = new HTTP::Cookies( file => "/tmp/lwp_cookies.dat" );
+
+my $rpc = new XMLRPC::Lite;
+
+$rpc->proxy('http://fedora/726193/xmlrpc.cgi');
+
+$rpc->encoding('UTF-8');
+
+$rpc->transport->cookie_jar($cookie_jar);
+
+my $call = $rpc->call( 'User.login',
+ { login => $username, password => $password } );
+
+if ( $call->faultstring ) {
+ print $call->faultstring . "\n";
+ exit;
+}
+
+# Save the cookies in the cookie file
+$rpc->transport->cookie_jar->extract_cookies(
+ $rpc->transport->http_response );
+$rpc->transport->cookie_jar->save;
+
+print "Successfully logged in.\n";
+
+###################################
+# Main call here #
+###################################
+
+my $attach_id = shift;
+my $action = shift;
+my $status = shift;
+
+$call = $rpc->call('TryAutoLand.update',
+ { attach_id => $attach_id, action => $action, status => $status });
+
+my $result = "";
+if ( $call->faultstring ) {
+ print $call->faultstring . "\n";
+ exit;
+}
+else {
+ $result = $call->result;
+}
+
+print Dumper($result);
diff --git a/extensions/TryAutoLand/bin/TryAutoLand.updateStatus_json.pl b/extensions/TryAutoLand/bin/TryAutoLand.updateStatus_json.pl
new file mode 100755
index 000000000..f39b55229
--- /dev/null
+++ b/extensions/TryAutoLand/bin/TryAutoLand.updateStatus_json.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl -w
+
+use JSON::RPC::Client;
+use Data::Dumper;
+use HTTP::Cookies;
+
+###################################
+# Need to login first #
+###################################
+
+my $username = shift;
+my $password = shift;
+
+my $cookie_jar = HTTP::Cookies->new( file => "/tmp/lwp_cookies.dat" );
+
+my $rpc = new JSON::RPC::Client;
+
+$rpc->ua->ssl_opts(verify_hostname => 0);
+
+my $uri = "http://fedora/726193/jsonrpc.cgi";
+
+#$rpc->ua->cookie_jar($cookie_jar);
+
+#my $result = $rpc->call($uri, { method => 'User.login', params =>
+# { login => $username, password => $password } });
+
+#if ($result) {
+# if ($result->is_error) {
+# print "Error : ", $result->error_message;
+# exit;
+# }
+# else {
+# print "Successfully logged in.\n";
+# }
+#}
+#else {
+# print $rpc->status_line;
+#}
+
+###################################
+# Main call here #
+###################################
+
+my $attach_id = shift;
+my $action = shift;
+my $status = shift;
+
+$result = $rpc->call($uri, { method => 'TryAutoLand.update',
+ params => { attach_id => $attach_id,
+ action => $action,
+ status => $status,
+ Bugzilla_login => $username,
+ Bugzilla_password => $password } });
+
+if ($result) {
+ if ($result->is_error) {
+ print "Error : ", $result->error_message;
+ exit;
+ }
+}
+else {
+ print $rpc->status_line;
+}
+
+print Dumper($result->result);
diff --git a/extensions/TryAutoLand/lib/Constants.pm b/extensions/TryAutoLand/lib/Constants.pm
new file mode 100644
index 000000000..53bad630a
--- /dev/null
+++ b/extensions/TryAutoLand/lib/Constants.pm
@@ -0,0 +1,31 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TryAutoLand::Constants;
+
+use strict;
+
+use base qw(Exporter);
+
+our @EXPORT = qw(
+ VALID_STATUSES
+ WEBSERVICE_USER
+ DEFAULT_TRY_SYNTAX
+);
+
+use constant VALID_STATUSES => qw(
+ waiting
+ running
+ failed
+ success
+);
+
+use constant WEBSERVICE_USER => 'autoland-try@mozilla.bugs';
+
+use constant DEFAULT_TRY_SYNTAX => '-b do -p all -u none -t none';
+
+1;
diff --git a/extensions/TryAutoLand/lib/WebService.pm b/extensions/TryAutoLand/lib/WebService.pm
new file mode 100644
index 000000000..1088386dd
--- /dev/null
+++ b/extensions/TryAutoLand/lib/WebService.pm
@@ -0,0 +1,189 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TryAutoLand::WebService;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::WebService);
+
+use Bugzilla::Error;
+use Bugzilla::Util qw(trick_taint);
+
+use Bugzilla::Extension::TryAutoLand::Constants;
+
+use constant READ_ONLY => qw(
+ getBugs
+);
+
+# TryAutoLand.getBugs
+# Params: status - List of statuses to filter attachments (only 'waiting' is default)
+# Returns: List of bugs, each being a hash of data needed by the AutoLand polling server
+# Params
+# [ { bug_id => $bug_id1, attachments => [ $attach_id1, $attach_id2 ] }, branches => $branchListFromTextField ... ]
+
+sub getBugs {
+ my ($self, $params) = @_;
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->dbh;
+ my %bugs;
+
+ if ($user->login ne WEBSERVICE_USER) {
+ ThrowUserError("auth_failure", { action => "access",
+ object => "autoland_attachments" });
+ }
+
+ my $status_where = "AND status = 'waiting'";
+ my $status_values = [];
+ if (exists $params->{'status'}) {
+ my $statuses = ref $params->{'status'}
+ ? $params->{'status'}
+ : [ $params->{'status'} ];
+ foreach my $status (@$statuses) {
+ if (grep($_ eq $status, VALID_STATUSES)) {
+ trick_taint($status);
+ push(@$status_values, $status);
+ }
+ }
+ if (@$status_values) {
+ my @qmarks = ("?") x @$status_values;
+ $status_where = "AND " . $dbh->sql_in('status', \@qmarks);
+ }
+
+ }
+
+ my $attachments = $dbh->selectall_arrayref("
+ SELECT attachments.bug_id,
+ attachments.attach_id,
+ autoland_attachments.who,
+ autoland_attachments.status,
+ autoland_attachments.status_when
+ FROM attachments, autoland_attachments
+ WHERE attachments.attach_id = autoland_attachments.attach_id
+ $status_where
+ ORDER BY attachments.bug_id",
+ undef, @$status_values);
+
+ foreach my $row (@$attachments) {
+ my ($bug_id, $attach_id, $al_who, $al_status, $al_status_when) = @$row;
+
+ my $al_user = Bugzilla::User->new($al_who);
+
+ # Silent Permission checks
+ next if !$user->can_see_bug($bug_id);
+ my $attachment = Bugzilla::Attachment->new($attach_id);
+ next if !$attachment
+ || $attachment->isobsolete
+ || ($attachment->isprivate && !$user->is_insider);
+
+ $bugs{$bug_id} = {} if !exists $bugs{$bug_id};
+
+ if (!$bugs{$bug_id}{'branches'}) {
+ my $bug_result = $dbh->selectrow_hashref("SELECT branches, try_syntax
+ FROM autoland_branches
+ WHERE bug_id = ?",
+ undef, $bug_id);
+ $bugs{$bug_id}{'branches'} = $bug_result->{'branches'};
+ $bugs{$bug_id}{'try_syntax'} = $bug_result->{'try_syntax'};
+ }
+
+ $bugs{$bug_id}{'attachments'} = [] if !exists $bugs{$bug_id}{'attachments'};
+
+ push(@{$bugs{$bug_id}{'attachments'}}, {
+ id => $self->type('int', $attach_id),
+ who => $self->type('string', $al_user->login),
+ status => $self->type('string', $al_status),
+ status_when => $self->type('dateTime', $al_status_when),
+ });
+ }
+
+ return [
+ map
+ { { bug_id => $_, attachments => $bugs{$_}{'attachments'},
+ branches => $bugs{$_}{'branches'}, try_syntax => $bugs{$_}{'try_syntax'} } }
+ keys %bugs
+ ];
+}
+
+# TryAutoLand.update({ attach_id => $attach_id, action => $action, status => $status })
+# Let's BMO know if a patch has landed or not and BMO will update the auto_land table accordingly
+# If $action eq 'status', $status will be a predetermined set of status values -- when waiting,
+# the UI for submitting autoland will be locked and once complete status update occurs or the
+# mapping is removed, the UI can be unlocked for the $attach_id
+# Allowed statuses: waiting, running, failed, or success
+#
+# If $action eq 'remove', the attach_id will be removed from the mapping table and the UI
+# will be unlocked for the $attach_id.
+
+sub update {
+ my ($self, $params) = @_;
+ my $user = Bugzilla->user;
+ my $dbh = Bugzilla->dbh;
+
+ if ($user->login ne WEBSERVICE_USER) {
+ ThrowUserError("auth_failure", { action => "modify",
+ object => "autoland_attachments" });
+ }
+
+ foreach my $param ('attach_id', 'action') {
+ defined $params->{$param}
+ || ThrowCodeError('param_required',
+ { param => $param });
+ }
+
+ my $action = delete $params->{'action'};
+ my $attach_id = delete $params->{'attach_id'};
+ my $status = delete $params->{'status'};
+
+ if ($action eq 'status' && !$status) {
+ ThrowCodeError('param_required', { param => 'status' });
+ }
+
+ grep($_ eq $action, ('remove', 'status'))
+ || ThrowUserError('autoland_update_invalid_action',
+ { action => $action,
+ valid => ["remove", "status"] });
+
+ my $attachment = Bugzilla::Attachment->new($attach_id);
+ $attachment
+ || ThrowUserError('autoland_invalid_attach_id',
+ { attach_id => $attach_id });
+
+ # Loud Permission checks
+ if (!$user->can_see_bug($attachment->bug_id)) {
+ ThrowUserError("bug_access_denied", { bug_id => $attachment->bug_id });
+ }
+ if ($attachment->isprivate && !$user->is_insider) {
+ ThrowUserError('auth_failure', { action => 'access',
+ object => 'attachment',
+ attach_id => $attachment->id });
+ }
+
+ $attachment->autoland_checked
+ || ThrowUserError('autoland_invalid_attach_id',
+ { attach_id => $attach_id });
+
+ if ($action eq 'status') {
+ # Update the status
+ $attachment->autoland_update_status($status);
+
+ return {
+ id => $self->type('int', $attachment->id),
+ who => $self->type('string', $attachment->autoland_who->login),
+ status => $self->type('string', $attachment->autoland_status),
+ status_when => $self->type('dateTime', $attachment->autoland_status_when),
+ };
+ }
+ elsif ($action eq 'remove') {
+ $attachment->autoland_remove();
+ }
+
+ return {};
+}
+
+1;
diff --git a/extensions/TryAutoLand/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/TryAutoLand/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
new file mode 100644
index 000000000..ed6224afe
--- /dev/null
+++ b/extensions/TryAutoLand/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,101 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF user.in_group('autoland') %]
+ [% autoland_attachments = [] %]
+ [% autoland_waiting = 0 %]
+ [% autoland_running = 0 %]
+ [% autoland_finished = 0 %]
+ [% FOREACH attachment = bug.attachments %]
+ [% NEXT IF attachment.isprivate && !user.is_insider && attachment.attacher.id != user.id %]
+ [% NEXT IF attachment.isobsolete %]
+ [% NEXT IF !attachment.ispatch %]
+ [% autoland_attachments.push(attachment) %]
+ [% IF attachment.autoland_checked %]
+ [% IF attachment.autoland_status == 'waiting' %]
+ [% autoland_waiting = autoland_waiting + 1 %]
+ [% END %]
+ [% IF attachment.autoland_status == 'running' %]
+ [% autoland_running = autoland_running + 1 %]
+ [% END %]
+ [% IF attachment.autoland_status == 'success' || attachment.autoland_status == 'failed' %]
+ [% autoland_finished = autoland_finished + 1 %]
+ [% END %]
+ [% END %]
+ [% END %]
+ [% IF autoland_attachments.size %]
+ <tr>
+ <th class="field_label field_land_autoland">
+ <a title="[% help_html.autoland FILTER txt FILTER collapse FILTER html %]"
+ class="field_help_link" href="https://wiki.mozilla.org/Build:Autoland">
+ AutoLand:</a>
+ </th>
+ <td>
+ <span id="autoland_edit_container">
+ (<a href="#" id="autoland_edit_action">edit</a>)
+ Total: [% autoland_attachments.size FILTER html %] -
+ <span class="autoland_waiting">Waiting:</span> [% autoland_waiting FILTER html %] -
+ <span class="autoland_running">Running:</span> [% autoland_running FILTER html %] -
+ <span class="autoland_success">Finished:</span> [% autoland_finished FILTER html %]
+ </span>
+ <div id="autoland_edit_input">
+ Branches (required):<br>
+ <input type="text" id="autoland_branches" name="autoland_branches"
+ value="[% bug.autoland_branches FILTER html %]" size="40"
+ class="text_input"><br>
+ Try Syntax (required): (Default: [% autoland_default_try_syntax FILTER html %])<br>
+ <input type="text" id="autoland_try_syntax" name="autoland_try_syntax"
+ value="[% bug.autoland_try_syntax || autoland_default_try_syntax FILTER html %]" size="40"
+ class="text_input"><br>
+ Patches:
+ <br>
+ <table id="autoland_edit_table">
+ [% FOREACH attachment = autoland_attachments %]
+ <tr>
+ <td>
+ [% IF attachment.autoland_checked %]
+ <input type="hidden" name="defined_autoland_attachments"
+ value="[% attachment.id FILTER html %]">
+ [% END %]
+ <input type="checkbox" name="autoland_attachments" value="[% attachment.id FILTER html %]"
+ [% ' checked="checked"' IF attachment.autoland_checked %]
+ [% IF attachment.autoland_status == 'running' || attachment.autoland_status == 'waiting' %]
+ disabled="disabled"
+ [% END %]>
+ </td>
+ <td>
+ <span title="[% attachment.description FILTER html %]">
+ [% attachment.filename FILTER html %]
+ </span>
+ <td>
+ [% IF attachment.autoland_checked %]
+ <span class="autoland_[% attachment.autoland_status FILTER html %]">
+ [% attachment.autoland_status FILTER html %]
+ </span>
+ [% END %]
+ </td>
+ <td>
+ [% IF attachment.autoland_checked %]
+ [% attachment.autoland_status_when FILTER time('%Y-%m-%d %H:%M') %]
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </div>
+ <script type="text/javascript">
+ hideEditableField('autoland_edit_container',
+ 'autoland_edit_input',
+ 'autoland_edit_action',
+ '',
+ '');
+ </script>
+ </td>
+ </tr>
+ [% END %]
+[% END %]
diff --git a/extensions/TryAutoLand/template/en/default/hook/bug/field-help-end.none.tmpl b/extensions/TryAutoLand/template/en/default/hook/bug/field-help-end.none.tmpl
new file mode 100644
index 000000000..899db60c4
--- /dev/null
+++ b/extensions/TryAutoLand/template/en/default/hook/bug/field-help-end.none.tmpl
@@ -0,0 +1,15 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%
+ vars.help_html.autoland =
+ "TryAutoLand is a BMO extension that allows integration with the $terms.Bugzilla
+ AutoLanding system. Select patches on a $terms.bug will be picked up
+ automatically and landed on the try build server for specified branches.
+ Results of the try build will be sent back to the bug report as comments."
+%]
diff --git a/extensions/TryAutoLand/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/TryAutoLand/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..c61f478ea
--- /dev/null
+++ b/extensions/TryAutoLand/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF autoland %]
+ [% style_urls.push('extensions/TryAutoLand/web/style.css') %]
+[% END %]
diff --git a/extensions/TryAutoLand/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl b/extensions/TryAutoLand/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
new file mode 100644
index 000000000..50a1e48d5
--- /dev/null
+++ b/extensions/TryAutoLand/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
@@ -0,0 +1,11 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF object == 'autoland_attachments' %]
+ AutoLand attachments
+[% END %]
diff --git a/extensions/TryAutoLand/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/TryAutoLand/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..c12950dcf
--- /dev/null
+++ b/extensions/TryAutoLand/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,33 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% IF error == "autoland_invalid_status" %]
+ [% title = "AutoLand Invalid Status" %]
+ The status '[% status FILTER html %]' is not a valid
+ status for the AutoLand extension. Valid statuses
+ are [% valid.join(', ') FILTER html %].
+
+[% ELSIF error == "autoland_invalid_attach_id" %]
+ [% title = "AutoLand Invalid Attachment ID" %]
+ The attachment id '[% attach_id FILTER html %]' is not
+ a valid id for the AutoLand extension.
+
+[% ELSIF error == "autoland_empty_try_syntax" %]
+ [% title = "AutoLand Empty Try Syntax" %]
+ You cannot have a value for Branches and have an empty Try Syntax value.
+
+[% ELSIF error == "autoland_empty_branches" %]
+ [% title = "AutoLand Empty Branches" %]
+ You cannot check one or more patches for AutoLanding and have an empty
+ Branches value.
+
+[% ELSIF error == "autoland_update_invalid_action" %]
+ [% title = "AutoLand Update Invalid Action" %]
+ The action '[% action FILTER html %]' is not a valid action.
+ Valid actions are [% valid.join(', ') FILTER html %].
+[% END %]
diff --git a/extensions/TryAutoLand/web/style.css b/extensions/TryAutoLand/web/style.css
new file mode 100644
index 000000000..99409c0c0
--- /dev/null
+++ b/extensions/TryAutoLand/web/style.css
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0.
+ */
+
+.autoland_waiting {
+ color: blue;
+}
+
+.autoland_running {
+ color: orange;
+}
+
+.autoland_failed {
+ color: red;
+}
+
+.autoland_success {
+ color: green;
+}
diff --git a/extensions/TypeSniffer/Config.pm b/extensions/TypeSniffer/Config.pm
new file mode 100644
index 000000000..6ad03b362
--- /dev/null
+++ b/extensions/TypeSniffer/Config.pm
@@ -0,0 +1,40 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the TypeSniffer Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is The Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@mozilla.org>
+
+package Bugzilla::Extension::TypeSniffer;
+use strict;
+
+use constant NAME => 'TypeSniffer';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'File-MimeInfo',
+ module => 'File::MimeInfo::Magic',
+ version => '0'
+ },
+ {
+ package => 'IO-stringy',
+ module => 'IO::Scalar',
+ version => '0'
+ },
+];
+
+__PACKAGE__->NAME; \ No newline at end of file
diff --git a/extensions/TypeSniffer/Extension.pm b/extensions/TypeSniffer/Extension.pm
new file mode 100644
index 000000000..78ecdcbef
--- /dev/null
+++ b/extensions/TypeSniffer/Extension.pm
@@ -0,0 +1,76 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the TypeSniffer Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is The Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@mozilla.org>
+
+package Bugzilla::Extension::TypeSniffer;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use File::MimeInfo::Magic;
+use IO::Scalar;
+
+our $VERSION = '0.02';
+################################################################################
+# This extension uses magic to guess MIME types for data where the browser has
+# told us it's application/octet-stream (probably because there's no file
+# extension, or it's a text type with a non-.txt file extension).
+################################################################################
+sub attachment_process_data {
+ my ($self, $args) = @_;
+ my $attributes = $args->{'attributes'};
+ my $params = Bugzilla->input_params;
+
+ # If we have autodetected application/octet-stream from the Content-Type
+ # header, let's have a better go using a sniffer.
+ if ($params->{'contenttypemethod'} &&
+ $params->{'contenttypemethod'} eq 'autodetect' &&
+ $attributes->{'mimetype'} eq 'application/octet-stream')
+ {
+ # data attribute can be either scalar data or filehandle
+ # bugzilla.org/docs/3.6/en/html/api/Bugzilla/Attachment.html#create
+ my $fh = $attributes->{'data'};
+ if (!ref($fh)) {
+ my $data = $attributes->{'data'};
+ $fh = new IO::Scalar \$data;
+ }
+ else {
+ # CGI.pm sends us an Fh that isn't actually an IO::Handle, but
+ # has a method for getting an actual handle out of it.
+ if (!$fh->isa('IO::Handle')) {
+ $fh = $fh->handle;
+ # ->handle returns an literal IO::Handle, even though the
+ # underlying object is a file. So we rebless it to be a proper
+ # IO::File object so that we can call ->seek on it and so on.
+ # Just in case CGI.pm fixes this some day, we check ->isa first.
+ if (!$fh->isa('IO::File')) {
+ bless $fh, 'IO::File';
+ }
+ }
+ }
+
+ my $mimetype = mimetype($fh);
+ $fh->seek(0, 0);
+ if ($mimetype) {
+ $attributes->{'mimetype'} = $mimetype;
+ }
+ }
+}
+
+__PACKAGE__->NAME;
diff --git a/extensions/Voting/Extension.pm b/extensions/Voting/Extension.pm
index a5a3bc11b..b8763b4df 100644
--- a/extensions/Voting/Extension.pm
+++ b/extensions/Voting/Extension.pm
@@ -47,6 +47,10 @@ use constant DEFAULT_VOTES_PER_BUG => 1;
use constant CMT_POPULAR_VOTES => 3;
use constant REL_VOTER => 4;
+BEGIN {
+ *Bugzilla::Bug::user_votes = \&_bug_user_votes;
+}
+
################
# Installation #
################
@@ -122,6 +126,15 @@ sub install_update_db {
# Objects #
###########
+sub _bug_user_votes {
+ my ($self) = @_;
+ return $self->{'user_votes'} if exists $self->{'user_votes'};
+ $self->{'user_votes'} = Bugzilla->dbh->selectrow_array(
+ "SELECT vote_count FROM votes WHERE bug_id = ? AND who = ?",
+ undef, $self->id, Bugzilla->user->id);
+ return $self->{'user_votes'};
+}
+
sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
diff --git a/extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl b/extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl
index f73ffaebd..b57a5cb27 100644
--- a/extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl
+++ b/extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl
@@ -29,6 +29,9 @@
[% ELSE %]
votes
[% END %]</a>
+ [% IF bug.user_votes %]
+ including you
+ [% END %]
[% END %]
(<a href="page.cgi?id=voting/user.html&amp;bug_id=
[%- bug.id FILTER uri %]#vote_
diff --git a/extensions/Voting/template/en/default/pages/voting/user.html.tmpl b/extensions/Voting/template/en/default/pages/voting/user.html.tmpl
index 61eaf8491..18221bda1 100644
--- a/extensions/Voting/template/en/default/pages/voting/user.html.tmpl
+++ b/extensions/Voting/template/en/default/pages/voting/user.html.tmpl
@@ -134,7 +134,7 @@
[% END %]
</a></td>
<td align="center">
- [% bug.id FILTER bug_link(bug) FILTER none %]
+ [% bug.id FILTER bug_link(bug.id) FILTER none %]
</td>
<td>
[% bug.summary FILTER html %]
diff --git a/images/buggie.png b/images/buggie.png
new file mode 100644
index 000000000..454a080a8
--- /dev/null
+++ b/images/buggie.png
Binary files differ
diff --git a/importxml.pl b/importxml.pl
index 896848b0a..7ed4c9f21 100755
--- a/importxml.pl
+++ b/importxml.pl
@@ -1208,7 +1208,7 @@ sub process_bug {
$c->{isprivate}, $c->{thetext}, 0);
}
$sth_comment->execute($id, $exporterid, $timestamp, 0, $comments, $worktime);
- Bugzilla::Bug->new($id)->_sync_fulltext('new_bug');
+ Bugzilla::Bug->new($id)->_sync_fulltext( new_bug => 1);
# Add this bug to each group of which its product is a member.
my $sth_group = $dbh->prepare("INSERT INTO bug_group_map (bug_id, group_id)
diff --git a/jobqueue.pl b/jobqueue.pl
index 775fe8dd6..38ea97eb2 100755
--- a/jobqueue.pl
+++ b/jobqueue.pl
@@ -60,6 +60,7 @@ jobqueue.pl - Runs jobs in the background for Bugzilla.
starts a new one.
once Checks the job queue once, executes the first item found (if
any) and then exits
+ onepass Checks the job queue, executes all items found, and then exits
check Report the current status of the daemon.
install On some *nix systems, this automatically installs and
configures jobqueue.pl as a system service so that it will
diff --git a/js/TUI.js b/js/TUI.js
index 34a79dc16..2dee8ab2e 100644
--- a/js/TUI.js
+++ b/js/TUI.js
@@ -69,8 +69,14 @@ function TUI_hide_default(className) {
function _TUI_toggle_control_link(className) {
var link = document.getElementById(className + "_controller");
if (!link) return;
- var original_text = link.innerHTML;
- link.innerHTML = TUI_alternates[className];
+ var original_text;
+ if (link.nodeName == 'INPUT') {
+ original_text = link.value;
+ link.value = TUI_alternates[className];
+ } else {
+ original_text = link.innerHTML;
+ link.innerHTML = TUI_alternates[className];
+ }
TUI_alternates[className] = original_text;
}
diff --git a/js/attachment.js b/js/attachment.js
index 7861164b1..f967f64d3 100644
--- a/js/attachment.js
+++ b/js/attachment.js
@@ -40,13 +40,12 @@ function updateCommentPrivacy(checkbox) {
}
}
-function setContentTypeDisabledState(form)
-{
+function setContentTypeDisabledState(form) {
var isdisabled = false;
if (form.ispatch.checked)
isdisabled = true;
- for (var i=0 ; i<form.contenttypemethod.length ; i++)
+ for (var i = 0; i < form.contenttypemethod.length; i++)
form.contenttypemethod[i].disabled = isdisabled;
form.contenttypeselection.disabled = isdisabled;
@@ -55,9 +54,8 @@ function setContentTypeDisabledState(form)
function TextFieldHandler() {
var field_text = document.getElementById("attach_text");
- var greyfields = new Array("data", "ispatch", "autodetect",
- "list", "manual", "contenttypeselection",
- "contenttypeentry");
+ var greyfields = new Array("data", "autodetect", "list", "manual",
+ "contenttypeselection", "contenttypeentry");
var i, thisfield;
if (field_text.value.match(/^\s*$/)) {
for (i = 0; i < greyfields.length; i++) {
diff --git a/js/comments.js b/js/comments.js
index e7163a0fd..e9a3e209f 100644
--- a/js/comments.js
+++ b/js/comments.js
@@ -143,3 +143,30 @@ function goto_add_comments( anchor ){
},10);
return false;
}
+
+if (typeof Node == 'undefined') {
+ /* MSIE doesn't define Node, so provide a compatibility object */
+ window.Node = {
+ TEXT_NODE: 3,
+ ENTITY_REFERENCE_NODE: 5
+ };
+}
+
+/* Concatenates all text from element's childNodes. This is used
+ * instead of innerHTML because we want the actual text (and
+ * innerText is non-standard).
+ */
+function getText(element) {
+ var child, text = "";
+ for (var i=0; i < element.childNodes.length; i++) {
+ child = element.childNodes[i];
+ var type = child.nodeType;
+ if (type == Node.TEXT_NODE || type == Node.ENTITY_REFERENCE_NODE) {
+ text += child.nodeValue;
+ } else {
+ /* recurse into nodes of other types */
+ text += getText(child);
+ }
+ }
+ return text;
+}
diff --git a/js/create_bug.js b/js/create_bug.js
new file mode 100644
index 000000000..62d24a642
--- /dev/null
+++ b/js/create_bug.js
@@ -0,0 +1,116 @@
+function toggleAdvancedFields() {
+ TUI_toggle_class('expert_fields');
+ var elements = YAHOO.util.Dom.getElementsByClassName('expert_fields');
+ if (YAHOO.util.Dom.hasClass(elements[0], TUI_HIDDEN_CLASS)) {
+ handleWantsBugFlags(false);
+ }
+}
+
+function handleWantsBugFlags(wants) {
+ if (wants) {
+ hideElementById('bug_flags_false');
+ showElementById('bug_flags_true');
+ }
+ else {
+ showElementById('bug_flags_false');
+ hideElementById('bug_flags_true');
+ clearBugFlagFields();
+ }
+}
+
+function clearBugFlagFields() {
+ var flags_table;
+ flags_table = document.getElementById('bug_flags');
+ if (flags_table) {
+ var selects = flags_table.getElementsByTagName('select');
+ for (var i = 0, il = selects.length; i < il; i++) {
+ if (selects[i].value != 'X') {
+ selects[i].value = 'X';
+ toggleRequesteeField(selects[i]);
+ }
+ }
+ }
+ flags_table = document.getElementById('bug_tracking_flags');
+ if (flags_table) {
+ var selects = flags_table.getElementsByTagName('select');
+ for (var i = 0, il = selects.length; i < il; i++) {
+ selects[i].value = '---';
+ }
+ }
+}
+
+YAHOO.util.Event.onDOMReady(function() {
+ function set_width(id, width) {
+ var el = document.getElementById(id);
+ if (!el) return;
+ el.style.width = width + 'px';
+ }
+
+ // force field widths
+
+ var width = document.getElementById('short_desc').clientWidth + 'px';
+ var el;
+
+ el = document.getElementById('comment');
+ el.style.width = width;
+
+ el = document.getElementById('cf_crash_signature');
+ if (el) el.style.width = width;
+
+ // show the bug flags if a flag is set
+
+ var flag_set = false;
+ var flags_table;
+ flags_table = document.getElementById('bug_flags');
+ if (flags_table) {
+ var selects = flags_table.getElementsByTagName('select');
+ for (var i = 0, il = selects.length; i < il; i++) {
+ if (selects[i].value != 'X') {
+ flag_set = true;
+ break;
+ }
+ }
+ }
+ if (!flag_set) {
+ flags_table = document.getElementById('bug_tracking_flags');
+ if (flags_table) {
+ var selects = flags_table.getElementsByTagName('select');
+ for (var i = 0, il = selects.length; i < il; i++) {
+ if (selects[i].value != '---') {
+ flag_set = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (flag_set) {
+ hideElementById('bug_flags_false');
+ showElementById('bug_flags_true');
+ } else {
+ hideElementById('bug_flags_true');
+ showElementById('bug_flags_false');
+ }
+ showElementById('btn_no_bug_flags')
+});
+
+function take_bug(user) {
+ var el = Dom.get('assigned_to');
+ el.value = user;
+ el.focus();
+ el.select();
+ assignee_change(user);
+ return false;
+}
+
+function assignee_change(user) {
+ var el = Dom.get('take_bug');
+ if (!el) return;
+ el.style.display = Dom.get('assigned_to').value == user ? 'none' : '';
+}
+
+function init_take_handler(user) {
+ YAHOO.util.Event.addListener(
+ 'assigned_to', 'change', function() { assignee_change(user); });
+ assignee_change(user);
+}
diff --git a/js/custom-search.js b/js/custom-search.js
index 73897035d..e5c172d3b 100644
--- a/js/custom-search.js
+++ b/js/custom-search.js
@@ -40,7 +40,7 @@ function custom_search_new_row() {
var row = document.getElementById('custom_search_last_row');
var clone = row.cloneNode(true);
- _cs_fix_ids(clone);
+ _cs_fix_row_ids(clone);
// We only want one copy of the buttons, in the new row. So the old
// ones get deleted.
@@ -55,13 +55,28 @@ function custom_search_new_row() {
// Always make sure there's only one row with this id.
row.id = null;
row.parentNode.appendChild(clone);
+ cs_reconfigure(row);
fix_query_string(row);
return clone;
}
+var _cs_source_any_all;
function custom_search_open_paren() {
var row = document.getElementById('custom_search_last_row');
+ // create a copy of j_top and use that as the source, so we can modify
+ // j_top if required
+ if (!_cs_source_any_all) {
+ var j_top = document.getElementById('j_top');
+ _cs_source_any_all = j_top.cloneNode(true);
+ }
+
+ // find the parent any/all select, and remove the grouped option
+ var structure = _cs_build_structure(row);
+ var old_id = _cs_get_row_id(row);
+ var parent_j = document.getElementById(_cs_get_join(structure, 'f' + old_id));
+ _cs_remove_and_g(parent_j);
+
// If there's an "Any/All" select in this row, it needs to stay as
// part of the parent paren set.
var old_any_all = _remove_any_all(row);
@@ -78,21 +93,20 @@ function custom_search_open_paren() {
var not_for_paren = new_not[0].cloneNode(true);
// Preserve the values when modifying the row.
- var id = _cs_fix_ids(row, true);
+ var id = _cs_fix_row_ids(row, true);
var prev_id = id - 1;
var paren_row = row.cloneNode(false);
paren_row.id = null;
paren_row.innerHTML = '(<input type="hidden" name="f' + prev_id
- + '" value="OP">';
+ + '" id="f' + prev_id + '" value="OP">';
paren_row.insertBefore(not_for_paren, paren_row.firstChild);
row.parentNode.insertBefore(paren_row, row);
-
+
// New paren set needs a new "Any/All" select.
var any_all_container = document.createElement('div');
YAHOO.util.Dom.addClass(any_all_container, ANY_ALL_SELECT_CLASS);
- var j_top = document.getElementById('j_top');
- var any_all = j_top.cloneNode(true);
+ var any_all = _cs_source_any_all.cloneNode(true);
any_all.name = 'j' + prev_id;
any_all.id = any_all.name;
any_all_container.appendChild(any_all);
@@ -104,6 +118,7 @@ function custom_search_open_paren() {
YAHOO.util.Dom.setStyle(row, 'margin-left', new_margin + 'em');
YAHOO.util.Dom.removeClass('cp_container', 'bz_default_hidden');
+ cs_reconfigure(any_all_container);
fix_query_string(any_all_container);
}
@@ -112,7 +127,7 @@ function custom_search_close_paren() {
// We need to up the new row's id by one more, because we're going
// to insert a "CP" before it.
- var id = _cs_fix_ids(new_row);
+ var id = _cs_fix_row_ids(new_row);
var margin = YAHOO.util.Dom.getStyle(new_row, 'margin-left');
var int_match = margin.match(/\d+/);
@@ -122,7 +137,7 @@ function custom_search_close_paren() {
var paren_row = new_row.cloneNode(false);
paren_row.id = null;
paren_row.innerHTML = ')<input type="hidden" name="f' + (id - 1)
- + '" value="CP">';
+ + '" id="f' + (id - 1) + '" value="CP">';
new_row.parentNode.insertBefore(paren_row, new_row);
@@ -130,6 +145,7 @@ function custom_search_close_paren() {
YAHOO.util.Dom.addClass('cp_container', 'bz_default_hidden');
}
+ cs_reconfigure(new_row);
fix_query_string(new_row);
}
@@ -172,19 +188,17 @@ function redirect_html4_browsers() {
document.location = url;
}
-function _cs_fix_ids(parent, preserve_values) {
+function _cs_fix_row_ids(row, preserve_values) {
// Update the label of the checkbox.
- var label = YAHOO.util.Dom.getElementBy(function() { return true },
- 'label', parent);
+ var label = YAHOO.util.Dom.getElementBy(function() { return true }, 'label', row);
var id_match = label.htmlFor.match(/\d+$/);
var id = parseInt(id_match[0]) + 1;
label.htmlFor = label.htmlFor.replace(/\d+$/, id);
- // Sets all the inputs in the parent back to their default
+ // Sets all the inputs in the row back to their default
// and fixes their id.
var fields =
- YAHOO.util.Dom.getElementsByClassName('custom_search_form_field', null,
- parent);
+ YAHOO.util.Dom.getElementsByClassName('custom_search_form_field', null, row);
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
@@ -196,15 +210,141 @@ function _cs_fix_ids(parent, preserve_values) {
field.value = '';
}
}
-
- // Update the numeric id for the new row.
+
+ // Update the numeric id for the row.
field.name = field.name.replace(/\d+$/, id);
field.id = field.name;
}
-
+
return id;
}
+function _cs_build_structure(form_member) {
+ // build a map of the structure of the custom fields
+ var form = YAHOO.util.Dom.getAncestorByTagName(form_member, 'form');
+ var last_id = _get_last_cs_row_id(form);
+ var structure = [ 'j_top' ];
+ var nested = [ structure ];
+ for (var id = 1; id <= last_id; id++) {
+ var f = form['f' + id];
+ if (!f || !f.parentNode.parentNode) continue;
+
+ if (f.value == 'OP') {
+ var j = [ 'j' + id ];
+ nested[nested.length - 1].push(j);
+ nested.push(j);
+ continue;
+ } else if (f.value == 'CP') {
+ nested.pop();
+ continue;
+ } else {
+ nested[nested.length - 1].push('f' + id);
+ }
+ }
+ return structure;
+}
+
+function cs_reconfigure(form_member) {
+ var structure = _cs_build_structure(form_member);
+ _cs_add_listeners(structure);
+ _cs_trigger_j_listeners(structure);
+ fix_query_string(form_member);
+
+ var j = _cs_get_join(structure, 'f' + _get_last_cs_row_id());
+ document.getElementById('op_button').disabled = document.getElementById(j).value == 'AND_G';
+}
+
+function _cs_add_listeners(parents) {
+ for (var i = 0, l = parents.length; i < l; i++) {
+ if (typeof(parents[i]) == 'object') {
+ // nested
+ _cs_add_listeners(parents[i]);
+ } else if (i == 0) {
+ // joiner
+ YAHOO.util.Event.removeListener(parents[i], 'change', _cs_j_change);
+ YAHOO.util.Event.addListener(parents[i], 'change', _cs_j_change, parents);
+ } else {
+ // field
+ YAHOO.util.Event.removeListener(parents[i], 'change', _cs_f_change);
+ YAHOO.util.Event.addListener(parents[i], 'change', _cs_f_change, parents);
+ }
+ }
+}
+
+function _cs_trigger_j_listeners(fields) {
+ var has_children = false;
+ for (var i = 0, l = fields.length; i < l; i++) {
+ if (typeof(fields[i]) == 'undefined') {
+ continue;
+ } else if (typeof(fields[i]) == 'object') {
+ // nested
+ _cs_trigger_j_listeners(fields[i]);
+ has_children = true;
+ } else if (i == 0) {
+ _cs_j_change(undefined, fields);
+ }
+ }
+ if (has_children) {
+ _cs_remove_and_g(document.getElementById(fields[0]));
+ }
+}
+
+function _cs_get_join(parents, field) {
+ for (var i = 0, l = parents.length; i < l; i++) {
+ if (typeof(parents[i]) == 'object') {
+ // nested
+ var result = _cs_get_join(parents[i], field);
+ if (result) return result;
+ } else if (parents[i] == field) {
+ return parents[0];
+ }
+ }
+ return false;
+}
+
+function _cs_remove_and_g(join_field) {
+ var index = bz_optionIndex(join_field, 'AND_G');
+ join_field.options[index] = null;
+ join_field.options[bz_optionIndex(join_field, 'AND')].innerHTML = cs_and_label;
+ join_field.options[bz_optionIndex(join_field, 'OR')].innerHTML = cs_or_label;
+}
+
+function _cs_j_change(evt, fields, field) {
+ var j = document.getElementById(fields[0]);
+ if (j && j.value == 'AND_G') {
+ for (var i = 1, l = fields.length; i < l; i++) {
+ if (typeof(fields[i]) == 'object') continue;
+ if (!field) {
+ field = document.getElementById(fields[i]).value;
+ } else {
+ document.getElementById(fields[i]).value = field;
+ }
+ }
+ if (evt) {
+ fix_query_string(j);
+ }
+ if ('f' + _get_last_cs_row_id() == fields[fields.length - 1]) {
+ document.getElementById('op_button').style.display = 'none';
+ }
+ } else {
+ document.getElementById('op_button').style.display = '';
+ }
+}
+
+function _cs_f_change(evt, args) {
+ var field = YAHOO.util.Event.getTarget(evt);
+ _cs_j_change(evt, args, field.value);
+}
+
+function _get_last_cs_row_id() {
+ return _cs_get_row_id('custom_search_last_row');
+}
+
+function _cs_get_row_id(row) {
+ var label = YAHOO.util.Dom.getElementBy(function() { return true }, 'label', row);
+ return parseInt(label.htmlFor.match(/\d+$/)[0]);
+}
+
function _remove_any_all(parent) {
var any_all = YAHOO.util.Dom.getElementsByClassName(
ANY_ALL_SELECT_CLASS, null, parent);
diff --git a/js/field.js b/js/field.js
index 07433b2a5..bfb8a8244 100644
--- a/js/field.js
+++ b/js/field.js
@@ -255,6 +255,8 @@ function showEditableField (e, ContainerInputArray) {
inputs.push(document.getElementById(ContainerInputArray[2]));
} else {
inputs = inputArea.getElementsByTagName('input');
+ if ( inputs.length == 0 )
+ inputs = inputArea.getElementsByTagName('textarea');
}
if ( inputs.length > 0 ) {
// Change the first field's value to ContainerInputArray[2]
@@ -288,7 +290,7 @@ function showEditableField (e, ContainerInputArray) {
*
* var e: the event
* var ContainerInputArray: An array containing the (edit) and text area and the input being displayed
- * var ContainerInputArray[0]: the conainer that will be hidden usually shows the (edit) text
+ * var ContainerInputArray[0]: the container that will be hidden usually shows the (edit) text
* var ContainerInputArray[1]: the input area and label that will be displayed
* var ContainerInputArray[2]: the field that is on the page, might get changed by browser autocomplete
* var ContainerInputArray[3]: the original value from the page loading.
@@ -299,7 +301,7 @@ function checkForChangedFieldValues(e, ContainerInputArray ) {
var unhide = false;
if ( el ) {
if ( el.value != ContainerInputArray[3] ||
- ( el.value == "" && el.id != "alias") ) {
+ ( el.value == "" && el.id != "alias" && el.id != "qa_contact" ) ) {
unhide = true;
}
else {
@@ -341,13 +343,19 @@ function showPeopleOnChange( field_id_list ) {
}
}
-function assignToDefaultOnChange(field_id_list) {
- showPeopleOnChange( field_id_list );
- for(var i = 0; i < field_id_list.length; i++) {
- YAHOO.util.Event.addListener( field_id_list[i],'change', setDefaultCheckbox,
- 'set_default_assignee');
- YAHOO.util.Event.addListener( field_id_list[i],'change',setDefaultCheckbox,
- 'set_default_qa_contact');
+function assignToDefaultOnChange(field_id_list, default_assignee, default_qa_contact) {
+ showPeopleOnChange(field_id_list);
+ for(var i = 0, l = field_id_list.length; i < l; i++) {
+ YAHOO.util.Event.addListener(field_id_list[i], 'change', function(evt, defaults) {
+ if (document.getElementById('assigned_to').value == defaults[0]) {
+ setDefaultCheckbox(evt, 'set_default_assignee');
+ }
+ if (document.getElementById('qa_contact')
+ && document.getElementById('qa_contact').value == defaults[1])
+ {
+ setDefaultCheckbox(evt, 'set_default_qa_contact');
+ }
+ }, [default_assignee, default_qa_contact]);
}
}
@@ -444,7 +452,7 @@ function setResolutionToDuplicate(e, duplicate_or_move_bug_status) {
YAHOO.util.Event.preventDefault(e);
}
-function setDefaultCheckbox(e, field_id ) {
+function setDefaultCheckbox(e, field_id) {
var el = document.getElementById(field_id);
var elLabel = document.getElementById(field_id + "_label");
if( el && elLabel ) {
@@ -714,9 +722,11 @@ YAHOO.bugzilla.userAutocomplete = {
},
debug_helper : function ( ){
/* used to help debug any errors that might happen */
+ /*
if( typeof(console) !== 'undefined' && console != null && arguments.length > 0 ){
console.log("debug helper info:", arguments);
}
+ */
return true;
},
init_ds : function(){
@@ -792,3 +802,51 @@ YAHOO.bugzilla.keywordAutocomplete = {
});
}
};
+
+/**
+ * Force the browser to honour the selected option when a page is refreshed,
+ * but only if the user hasn't explicitly selected a different option.
+ */
+function initDirtyFieldTracking() {
+ // old IE versions don't provide the information we need to make this fix work
+ // however they aren't affected by this issue, so it's ok to ignore them
+ if (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie <= 8) return;
+ var selects = document.getElementById('changeform').getElementsByTagName('select');
+ for (var i = 0, l = selects.length; i < l; i++) {
+ var el = selects[i];
+ var el_dirty = document.getElementById(el.name + '_dirty');
+ if (!el_dirty) continue;
+ if (!el_dirty.value) {
+ var preSelected = bz_preselectedOptions(el);
+ if (!el.multiple) {
+ preSelected.selected = true;
+ } else {
+ el.selectedIndex = -1;
+ for (var j = 0, m = preSelected.length; j < m; j++) {
+ preSelected[j].selected = true;
+ }
+ }
+ }
+ YAHOO.util.Event.on(el, "change", function(e) {
+ var el = e.target || e.srcElement;
+ var preSelected = bz_preselectedOptions(el);
+ var currentSelected = bz_selectedOptions(el);
+ var isDirty = false;
+ if (!el.multiple) {
+ isDirty = preSelected.index != currentSelected.index;
+ } else {
+ if (preSelected.length != currentSelected.length) {
+ isDirty = true;
+ } else {
+ for (var i = 0, l = preSelected.length; i < l; i++) {
+ if (currentSelected[i].index != preSelected[i].index) {
+ isDirty = true;
+ break;
+ }
+ }
+ }
+ }
+ document.getElementById(el.name + '_dirty').value = isDirty ? '1' : '';
+ });
+ }
+}
diff --git a/js/instant-search.js b/js/instant-search.js
new file mode 100644
index 000000000..a3f051f2f
--- /dev/null
+++ b/js/instant-search.js
@@ -0,0 +1,201 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+var Dom = YAHOO.util.Dom;
+var Event = YAHOO.util.Event;
+
+Event.onDOMReady(function() {
+ YAHOO.bugzilla.instantSearch.onInit();
+ if (YAHOO.bugzilla.instantSearch.getContent().length >= 4) {
+ YAHOO.bugzilla.instantSearch.doSearch(YAHOO.bugzilla.instantSearch.getContent());
+ } else {
+ YAHOO.bugzilla.instantSearch.reset();
+ }
+ Dom.get('content').focus();
+});
+
+YAHOO.bugzilla.instantSearch = {
+ counter: 0,
+ dataTable: null,
+ dataTableColumns: null,
+ elContent: null,
+ elList: null,
+ currentSearchQuery: '',
+ currentSearchProduct: '',
+
+ onInit: function() {
+ YAHOO.util.Connect.setDefaultPostHeader('application/json; charset=UTF-8');
+
+ this.elContent = Dom.get('content');
+ this.elList = Dom.get('results');
+
+ Event.addListener(this.elContent, 'keyup', this.onContentKeyUp);
+ Event.addListener(Dom.get('product'), 'change', this.onProductChange);
+ },
+
+ setLabels: function(labels) {
+ this.dataTableColumns = [
+ { key: "id", label: labels.id, formatter: this.formatId },
+ { key: "summary", label: labels.summary, formatter: "text" },
+ { key: "component", label: labels.component, formatter: "text" },
+ { key: "status", label: labels.status, formatter: this.formatStatus },
+ ];
+ },
+
+ initDataTable: function() {
+ var dataSource = new YAHOO.util.XHRDataSource("jsonrpc.cgi");
+ dataSource.connTimeout = 15000;
+ dataSource.connMethodPost = true;
+ dataSource.connXhrMode = "cancelStaleRequests";
+ dataSource.maxCacheEntries = 3;
+ dataSource.responseSchema = {
+ resultsList : "result.bugs",
+ metaFields : { error: "error", jsonRpcId: "id" }
+ };
+ // DataSource can't understand a JSON-RPC error response, so
+ // we have to modify the result data if we get one.
+ dataSource.doBeforeParseData =
+ function(oRequest, oFullResponse, oCallback) {
+ if (oFullResponse.error) {
+ oFullResponse.result = {};
+ oFullResponse.result.bugs = [];
+ if (console)
+ console.error("JSON-RPC error:", oFullResponse.error);
+ }
+ return oFullResponse;
+ };
+ dataSource.subscribe('dataErrorEvent',
+ function() {
+ YAHOO.bugzilla.instantSearch.currentSearchQuery = '';
+ }
+ );
+
+ this.dataTable = new YAHOO.widget.DataTable(
+ 'results',
+ this.dataTableColumns,
+ dataSource,
+ {
+ initialLoad: false,
+ MSG_EMPTY: 'No matching bugs found.',
+ MSG_ERROR: 'An error occurred while searching for bugs, please try again.'
+ }
+ );
+ },
+
+ formatId: function(el, oRecord, oColumn, oData) {
+ el.innerHTML = '<a href="show_bug.cgi?id=' + oData + '" target="_blank">' + oData + '</a>';
+ },
+
+ formatStatus: function(el, oRecord, oColumn, oData) {
+ var resolution = oRecord.getData('resolution');
+ var bugStatus = display_value('bug_status', oData);
+ if (resolution) {
+ el.innerHTML = bugStatus + ' ' + display_value('resolution', resolution);
+ } else {
+ el.innerHTML = bugStatus;
+ }
+ },
+
+ reset: function() {
+ Dom.addClass(this.elList, 'hidden');
+ this.elList.innerHTML = '';
+ this.currentSearchQuery = '';
+ this.currentSearchProduct = '';
+ },
+
+ onContentKeyUp: function(e) {
+ clearTimeout(YAHOO.bugzilla.instantSearch.lastTimeout);
+ YAHOO.bugzilla.instantSearch.lastTimeout = setTimeout(function() {
+ YAHOO.bugzilla.instantSearch.doSearch(YAHOO.bugzilla.instantSearch.getContent()) },
+ 600);
+ },
+
+ onProductChange: function(e) {
+ YAHOO.bugzilla.instantSearch.doSearch(YAHOO.bugzilla.instantSearch.getContent());
+ },
+
+ doSearch: function(query) {
+ if (query.length < 4)
+ return;
+
+ // don't query if we already have the results (or they are pending)
+ var product = Dom.get('product').value;
+ if (YAHOO.bugzilla.instantSearch.currentSearchQuery == query &&
+ YAHOO.bugzilla.instantSearch.currentSearchProduct == product)
+ return;
+ YAHOO.bugzilla.instantSearch.currentSearchQuery = query;
+ YAHOO.bugzilla.instantSearch.currentSearchProduct = product;
+
+ // initialise the datatable as late as possible
+ YAHOO.bugzilla.instantSearch.initDataTable();
+
+ try {
+ // run the search
+ Dom.removeClass(YAHOO.bugzilla.instantSearch.elList, 'hidden');
+
+ YAHOO.bugzilla.instantSearch.dataTable.showTableMessage(
+ 'Searching...&nbsp;&nbsp;&nbsp;' +
+ '<img src="extensions/GuidedBugEntry/web/images/throbber.gif"' +
+ ' width="16" height="11">',
+ YAHOO.widget.DataTable.CLASS_LOADING
+ );
+ var jsonObject = {
+ version: "1.1",
+ method: "Bug.possible_duplicates",
+ id: ++YAHOO.bugzilla.instantSearch.counter,
+ params: {
+ product: YAHOO.bugzilla.instantSearch.getProduct(),
+ summary: query,
+ limit: 20,
+ include_fields: [ "id", "summary", "status", "resolution", "component" ]
+ }
+ };
+
+ YAHOO.bugzilla.instantSearch.dataTable.getDataSource().sendRequest(
+ YAHOO.lang.JSON.stringify(jsonObject),
+ {
+ success: YAHOO.bugzilla.instantSearch.onSearchResults,
+ failure: YAHOO.bugzilla.instantSearch.onSearchResults,
+ scope: YAHOO.bugzilla.instantSearch.dataTable,
+ argument: YAHOO.bugzilla.instantSearch.dataTable.getState()
+ }
+ );
+
+ } catch(err) {
+ if (console)
+ console.error(err.message);
+ }
+ },
+
+ onSearchResults: function(sRequest, oResponse, oPayload) {
+ YAHOO.bugzilla.instantSearch.dataTable.onDataReturnInitializeTable(sRequest, oResponse, oPayload);
+ },
+
+ getContent: function() {
+ var content = YAHOO.lang.trim(this.elContent.value);
+ // work around chrome bug
+ if (content == YAHOO.bugzilla.instantSearch.elContent.getAttribute('placeholder')) {
+ return '';
+ } else {
+ return content;
+ }
+ },
+
+ getProduct: function() {
+ var result = [];
+ var name = Dom.get('product').value;
+ result.push(name);
+ if (products[name] && products[name].related) {
+ for (var i = 0, n = products[name].related.length; i < n; i++) {
+ result.push(products[name].related[i]);
+ }
+ }
+ return result;
+ }
+
+};
+
diff --git a/js/util.js b/js/util.js
index 6dcabbbc9..e0e87259f 100644
--- a/js/util.js
+++ b/js/util.js
@@ -202,6 +202,55 @@ function bz_populateSelectFromArray(aSelect, aArray) {
}
/**
+ * Returns all Option elements that are selected in a <select>,
+ * as an array. Returns an empty array if nothing is selected.
+ *
+ * @param aSelect The select you want the selected values of.
+ */
+function bz_selectedOptions(aSelect) {
+ // HTML 5
+ if (aSelect.selectedOptions) {
+ return aSelect.selectedOptions;
+ }
+
+ var start_at = aSelect.selectedIndex;
+ if (start_at == -1) return [];
+ var first_selected = aSelect.options[start_at];
+ if (!aSelect.multiple) return first_selected;
+ // selectedIndex is specified as being the "first selected item",
+ // so we can start from there.
+ var selected = [first_selected];
+ var options_length = aSelect.options.length;
+ // We start after first_selected
+ for (var i = start_at + 1; i < options_length; i++) {
+ var this_option = aSelect.options[i];
+ if (this_option.selected) selected.push(this_option);
+ }
+ return selected;
+}
+
+/**
+ * Returns all Option elements that have the "selected" attribute, as an array.
+ * Returns an empty array if nothing is selected.
+ *
+ * @param aSelect The select you want the pre-selected values of.
+ */
+function bz_preselectedOptions(aSelect) {
+ var options = aSelect.options;
+ var selected = new Array();
+ for (var i = 0, l = options.length; i < l; i++) {
+ var attributes = options[i].attributes;
+ for (var j = 0, m = attributes.length; j < m; j++) {
+ if (attributes[j].name == 'selected') {
+ if (!aSelect.multiple) return options[i];
+ selected.push(options[i]);
+ }
+ }
+ }
+ return selected;
+}
+
+/**
* Tells you whether or not a particular value is selected in a select,
* whether it's a multi-select or a single-select. The check is
* case-sensitive.
diff --git a/js/yui3/align-plugin/align-plugin-min.js b/js/yui3/align-plugin/align-plugin-min.js
new file mode 100644
index 000000000..f71a3b0e6
--- /dev/null
+++ b/js/yui3/align-plugin/align-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("align-plugin",function(e,t){function s(e){e.host&&(this._host=e.host)}var n="offsetWidth",r="offsetHeight",i=i;s.prototype={to:function(t,o,u,a){this._syncArgs=e.Array(arguments),t.top===i&&(t=e.one(t).get("region"));if(t){var f=[t.left,t.top],l=[t.width,t.height],c=s.points,h=this._host,p=null,d=h.getAttrs([r,n]),v=[0-d[n],0-d[r]],m=o?c[o.charAt(0)]:p,g=o&&o!=="cc"?c[o.charAt(1)]:p,y=u?c[u.charAt(0)]:p,b=u&&u!=="cc"?c[u.charAt(1)]:p;m&&(f=m(f,l,o)),g&&(f=g(f,l,o)),y&&(f=y(f,v,u)),b&&(f=b(f,v,u)),f&&h&&h.setXY(f),this._resize(a)}return this},sync:function(){return this.to.apply(this,this._syncArgs),this},_resize:function(t){var n=this._handle;t&&!n?this._handle=e.on("resize",this._onresize,window,this):!t&&n&&n.detach()},_onresize:function(){var e=this;setTimeout(function(){e.sync()})},center:function(e,t){return this.to(e,"cc","cc",t),this},destroy:function(){var e=this._handle;e&&e.detach()}},s.points={t:function(e,t){return e},r:function(e,t){return[e[0]+t[0],e[1]]},b:function(e,t){return[e[0],e[1]+t[1]]},l:function(e,t){return e},c:function(e,t,n){var r=n[0]==="t"||n[0]==="b"?0:1,i,s;return n==="cc"?i=[e[0]+t[0]/2,e[1]+t[1]/2]:(s=e[r]+t[r]/2,i=r?[e[0],s]:[s,e[1]]),i}},s.NAME="Align",s.NS="align",s.prototype.constructor=s,e.namespace("Plugin"),e.Plugin.Align=s},"3.7.3",{requires:["node-screen","node-pluginhost"]});
diff --git a/js/yui3/anim-base/anim-base-min.js b/js/yui3/anim-base/anim-base-min.js
new file mode 100644
index 000000000..4f556ed06
--- /dev/null
+++ b/js/yui3/anim-base/anim-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-base",function(e,t){var n="running",r="startTime",i="elapsedTime",s="start",o="tween",u="end",a="node",f="paused",l="reverse",c="iterationCount",h=Number,p={},d;e.Anim=function(){e.Anim.superclass.constructor.apply(this,arguments),e.Anim._instances[e.stamp(this)]=this},e.Anim.NAME="anim",e.Anim._instances={},e.Anim.RE_DEFAULT_UNIT=/^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,e.Anim.DEFAULT_UNIT="px",e.Anim.DEFAULT_EASING=function(e,t,n,r){return n*e/r+t},e.Anim._intervalTime=20,e.Anim.behaviors={left:{get:function(e,t){return e._getOffset(t)}}},e.Anim.behaviors.top=e.Anim.behaviors.left,e.Anim.DEFAULT_SETTER=function(t,n,r,i,s,o,u,a){var f=t._node,l=f._node,c=u(s,h(r),h(i)-h(r),o);l?"style"in l&&(n in l.style||n in e.DOM.CUSTOM_STYLES)?(a=a||"",f.setStyle(n,c+a)):"attributes"in l&&n in l.attributes?f.setAttribute(n,c):n in l&&(l[n]=c):f.set?f.set(n,c):n in f&&(f[n]=c)},e.Anim.DEFAULT_GETTER=function(t,n){var r=t._node,i=r._node,s="";return i?"style"in i&&(n in i.style||n in e.DOM.CUSTOM_STYLES)?s=r.getComputedStyle(n):"attributes"in i&&n in i.attributes?s=r.getAttribute(n):n in i&&(s=i[n]):r.get?s=r.get(n):n in r&&(s=r[n]),s},e.Anim.ATTRS={node:{setter:function(t){return t&&(typeof t=="string"||t.nodeType)&&(t=e.one(t)),this._node=t,!t,t}},duration:{value:1},easing:{value:e.Anim.DEFAULT_EASING,setter:function(t){if(typeof t=="string"&&e.Easing)return e.Easing[t]}},from:{},to:{},startTime:{value:0,readOnly:!0},elapsedTime:{value:0,readOnly:!0},running:{getter:function(){return!!p[e.stamp(this)]},value:!1,readOnly:!0},iterations:{value:1},iterationCount:{value:0,readOnly:!0},direction:{value:"normal"},paused:{readOnly:!0,value:!1},reverse:{value:!1}},e.Anim.run=function(){var t=e.Anim._instances;for(var n in t)t[n].run&&t[n].run()},e.Anim.pause=function(){for(var t in p)p[t].pause&&p[t].pause();e.Anim._stopTimer()},e.Anim.stop=function(){for(var t in p)p[t].stop&&p[t].stop();e.Anim._stopTimer()},e.Anim._startTimer=function(){d||(d=setInterval(e.Anim._runFrame,e.Anim._intervalTime))},e.Anim._stopTimer=function(){clearInterval(d),d=0},e.Anim._runFrame=function(){var t=!0;for(var n in p)p[n]._runFrame&&(t=!1,p[n]._runFrame());t&&e.Anim._stopTimer()},e.Anim.RE_UNITS=/^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;var v={run:function(){return this.get(f)?this._resume():this.get(n)||this._start(),this},pause:function(){return this.get(n)&&this._pause(),this},stop:function(e){return(this.get(n)||this.get(f))&&this._end(e),this},_added:!1,_start:function(){this._set(r,new Date-this.get(i)),this._actualFrames=0,this.get(f)||this._initAnimAttr(),p[e.stamp(this)]=this,e.Anim._startTimer(),this.fire(s)},_pause:function(){this._set(r,null),this._set(f,!0),delete p[e.stamp(this)],this.fire("pause")},_resume:function(){this._set(f,!1),p[e.stamp(this)]=this,this._set(r,new Date-this.get(i)),e.Anim._startTimer(),this.fire("resume")},_end:function(t){var n=this.get("duration")*1e3;t&&this._runAttrs(n,n,this.get(l)),this._set(r,null),this._set(i,0),this._set(f,!1),delete p[e.stamp(this)],this.fire(u,{elapsed:this.get(i)})},_runFrame:function(){var e=this._runtimeAttr.duration,t=new Date-this.get(r),n=this.get(l),s=t>=e,u,a;this._runAttrs(t,e,n),this._actualFrames+=1,this._set(i,t),this.fire(o),s&&this._lastFrame()},_runAttrs:function(t,n,r){var i=this._runtimeAttr,s=e.Anim.behaviors,o=i.easing,u=n,a=!1,f,l,c;t>=n&&(a=!0),r&&(t=n-t,u=0);for(c in i)i[c].to&&(f=i[c],l=c in s&&"set"in s[c]?s[c].set:e.Anim.DEFAULT_SETTER,a?l(this,c,f.from,f.to,u,n,o,f.unit):l(this,c,f.from,f.to,t,n,o,f.unit))},_lastFrame:function(){var e=this.get("iterations"),t=this.get(c);t+=1,e==="infinite"||t<e?(this.get("direction")==="alternate"&&this.set(l,!this.get(l)),this.fire("iteration")):(t=0,this._end()),this._set(r,new Date),this._set(c,t)},_initAnimAttr:function(){var t=this.get("from")||{},n=this.get("to")||{},r={duration:this.get("duration")*1e3,easing:this.get("easing")},i=e.Anim.behaviors,s=this.get(a),o,u,f;e.each(n,function(n,a){typeof n=="function"&&(n=n.call(this,s)),u=t[a],u===undefined?u=a in i&&"get"in i[a]?i[a].get(this,a):e.Anim.DEFAULT_GETTER(this,a):typeof u=="function"&&(u=u.call(this,s));var l=e.Anim.RE_UNITS.exec(u),c=e.Anim.RE_UNITS.exec(n);u=l?l[1]:u,f=c?c[1]:n,o=c?c[2]:l?l[2]:"",!o&&e.Anim.RE_DEFAULT_UNIT.test(a)&&(o=e.Anim.DEFAULT_UNIT);if(!u||!f){e.error('invalid "from" or "to" for "'+a+'"',"Anim");return}r[a]={from:e.Lang.isObject(u)?e.clone(u):u,to:f,unit:o}},this),this._runtimeAttr=r},_getOffset:function(e){var t=this._node,n=t.getComputedStyle(e),r=e==="left"?"getX":"getY",i=e==="left"?"setX":"setY";if(n==="auto"){var s=t.getStyle("position");s==="absolute"||s==="fixed"?(n=t[r](),t[i](n)):n=0}return n},destructor:function(){delete e.Anim._instances[e.stamp(this)]}};e.extend(e.Anim,e.Base,v)},"3.7.3",{requires:["base-base","node-style"]});
diff --git a/js/yui3/anim-color/anim-color-min.js b/js/yui3/anim-color/anim-color-min.js
new file mode 100644
index 000000000..27d294286
--- /dev/null
+++ b/js/yui3/anim-color/anim-color-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-color",function(e,t){var n=Number;e.Anim.getUpdatedColorValue=function(t,r,i,s,o){return t=e.Color.re_RGB.exec(e.Color.toRGB(t)),r=e.Color.re_RGB.exec(e.Color.toRGB(r)),(!t||t.length<3||!r||r.length<3)&&e.error("invalid from or to passed to color behavior"),"rgb("+[Math.floor(o(i,n(t[1]),n(r[1])-n(t[1]),s)),Math.floor(o(i,n(t[2]),n(r[2])-n(t[2]),s)),Math.floor(o(i,n(t[3]),n(r[3])-n(t[3]),s))].join(", ")+")"},e.Anim.behaviors.color={set:function(t,n,r,i,s,o,u){t._node.setStyle(n,e.Anim.getUpdatedColorValue(r,i,s,o,u))},get:function(e,t){var n=e._node.getComputedStyle(t);return n=n==="transparent"?"rgb(255, 255, 255)":n,n}},e.each(["backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor"],function(t,n){e.Anim.behaviors[t]=e.Anim.behaviors.color})},"3.7.3",{requires:["anim-base"]});
diff --git a/js/yui3/anim-curve/anim-curve-min.js b/js/yui3/anim-curve/anim-curve-min.js
new file mode 100644
index 000000000..6bb8d66d9
--- /dev/null
+++ b/js/yui3/anim-curve/anim-curve-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-curve",function(e,t){e.Anim.behaviors.curve={set:function(t,n,r,i,s,o,u){r=r.slice.call(r),i=i.slice.call(i);var a=u(s,0,100,o)/100;i.unshift(r),t._node.setXY(e.Anim.getBezier(i,a))},get:function(e,t){return e._node.getXY()}},e.Anim.getBezier=function(e,t){var n=e.length,r=[];for(var i=0;i<n;++i)r[i]=[e[i][0],e[i][1]];for(var s=1;s<n;++s)for(i=0;i<n-s;++i)r[i][0]=(1-t)*r[i][0]+t*r[parseInt(i+1,10)][0],r[i][1]=(1-t)*r[i][1]+t*r[parseInt(i+1,10)][1];return[r[0][0],r[0][1]]}},"3.7.3",{requires:["anim-xy"]});
diff --git a/js/yui3/anim-easing/anim-easing-min.js b/js/yui3/anim-easing/anim-easing-min.js
new file mode 100644
index 000000000..62269bf53
--- /dev/null
+++ b/js/yui3/anim-easing/anim-easing-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-easing",function(e,t){var n={easeNone:function(e,t,n,r){return n*e/r+t},easeIn:function(e,t,n,r){return n*(e/=r)*e+t},easeOut:function(e,t,n,r){return-n*(e/=r)*(e-2)+t},easeBoth:function(e,t,n,r){return(e/=r/2)<1?n/2*e*e+t:-n/2*(--e*(e-2)-1)+t},easeInStrong:function(e,t,n,r){return n*(e/=r)*e*e*e+t},easeOutStrong:function(e,t,n,r){return-n*((e=e/r-1)*e*e*e-1)+t},easeBothStrong:function(e,t,n,r){return(e/=r/2)<1?n/2*e*e*e*e+t:-n/2*((e-=2)*e*e*e-2)+t},elasticIn:function(e,t,n,r,i,s){var o;return e===0?t:(e/=r)===1?t+n:(s||(s=r*.3),!i||i<Math.abs(n)?(i=n,o=s/4):o=s/(2*Math.PI)*Math.asin(n/i),-(i*Math.pow(2,10*(e-=1))*Math.sin((e*r-o)*2*Math.PI/s))+t)},elasticOut:function(e,t,n,r,i,s){var o;return e===0?t:(e/=r)===1?t+n:(s||(s=r*.3),!i||i<Math.abs(n)?(i=n,o=s/4):o=s/(2*Math.PI)*Math.asin(n/i),i*Math.pow(2,-10*e)*Math.sin((e*r-o)*2*Math.PI/s)+n+t)},elasticBoth:function(e,t,n,r,i,s){var o;return e===0?t:(e/=r/2)===2?t+n:(s||(s=r*.3*1.5),!i||i<Math.abs(n)?(i=n,o=s/4):o=s/(2*Math.PI)*Math.asin(n/i),e<1?-0.5*i*Math.pow(2,10*(e-=1))*Math.sin((e*r-o)*2*Math.PI/s)+t:i*Math.pow(2,-10*(e-=1))*Math.sin((e*r-o)*2*Math.PI/s)*.5+n+t)},backIn:function(e,t,n,r,i){return i===undefined&&(i=1.70158),e===r&&(e-=.001),n*(e/=r)*e*((i+1)*e-i)+t},backOut:function(e,t,n,r,i){return typeof i=="undefined"&&(i=1.70158),n*((e=e/r-1)*e*((i+1)*e+i)+1)+t},backBoth:function(e,t,n,r,i){return typeof i=="undefined"&&(i=1.70158),(e/=r/2)<1?n/2*e*e*(((i*=1.525)+1)*e-i)+t:n/2*((e-=2)*e*(((i*=1.525)+1)*e+i)+2)+t},bounceIn:function(t,n,r,i){return r-e.Easing.bounceOut(i-t,0,r,i)+n},bounceOut:function(e,t,n,r){return(e/=r)<1/2.75?n*7.5625*e*e+t:e<2/2.75?n*(7.5625*(e-=1.5/2.75)*e+.75)+t:e<2.5/2.75?n*(7.5625*(e-=2.25/2.75)*e+.9375)+t:n*(7.5625*(e-=2.625/2.75)*e+.984375)+t},bounceBoth:function(t,n,r,i){return t<i/2?e.Easing.bounceIn(t*2,0,r,i)*.5+n:e.Easing.bounceOut(t*2-i,0,r,i)*.5+r*.5+n}};e.Easing=n},"3.7.3",{requires:["anim-base"]});
diff --git a/js/yui3/anim-node-plugin/anim-node-plugin-min.js b/js/yui3/anim-node-plugin/anim-node-plugin-min.js
new file mode 100644
index 000000000..9d5246062
--- /dev/null
+++ b/js/yui3/anim-node-plugin/anim-node-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-node-plugin",function(e,t){var n=function(t){t=t?e.merge(t):{},t.node=t.host,n.superclass.constructor.apply(this,arguments)};n.NAME="nodefx",n.NS="fx",e.extend(n,e.Anim),e.namespace("Plugin"),e.Plugin.NodeFX=n},"3.7.3",{requires:["node-pluginhost","anim-base"]});
diff --git a/js/yui3/anim-scroll/anim-scroll-min.js b/js/yui3/anim-scroll/anim-scroll-min.js
new file mode 100644
index 000000000..5e8b6d22e
--- /dev/null
+++ b/js/yui3/anim-scroll/anim-scroll-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-scroll",function(e,t){var n=Number;e.Anim.behaviors.scroll={set:function(e,t,r,i,s,o,u){var a=e._node,f=[u(s,n(r[0]),n(i[0])-n(r[0]),o),u(s,n(r[1]),n(i[1])-n(r[1]),o)];f[0]&&a.set("scrollLeft",f[0]),f[1]&&a.set("scrollTop",f[1])},get:function(e){var t=e._node;return[t.get("scrollLeft"),t.get("scrollTop")]}}},"3.7.3",{requires:["anim-base"]});
diff --git a/js/yui3/anim-shape/anim-shape-min.js b/js/yui3/anim-shape/anim-shape-min.js
new file mode 100644
index 000000000..b70c67f67
--- /dev/null
+++ b/js/yui3/anim-shape/anim-shape-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-shape",function(e,t){var n=Number,r,i,s="color",o="stops",u="type",a=function(t,r,i,o,u,a){var f=0,l=e.Anim.getUpdatedColorValue,c,h,p,d=i.length,v,m,g,y,b,w,E,S,x,T=[],N;for(;f<d;f+=1){c=i[f],h=r[f],N={};for(p in c)c.hasOwnProperty(p)&&(p==s?N[p]=e.Color.toHex(l(e.Color.toHex(h[p]),e.Color.toHex(c[p]),o,u,a)):N[p]=a(o,n(h[p]),n(c[p])-n(h[p]),u));T.push(N)}return T},f={set:function(t,r,i,f,l,c,h){var p,d={},v=e.Anim.getUpdatedColorValue,m=a;for(p in f)if(f.hasOwnProperty(p)&&p!=u)switch(p){case s:d[p]=v(i[p],f[p],l,c,h);break;case o:d[p]=m(t,i[p],f[p],l,c,h);break;default:d[p]=h(l,n(i[p]),n(f[p])-n(i[p]),c)}t._node.set(r,d)}};e.Anim.behaviors.fill=f,e.Anim.behaviors.stroke=f,e.Anim.behaviors.transform={set:function(e,t,s,o,u,a,f){var l=e._node,c="",h,p,d,v,m=0,g,y,b;o=r,b=r.length;for(;m<b;++m){d=o[m].concat(),v=s[m].concat(),h=d.shift(),p=v.shift(),y=d.length,c+=h+"(";for(g=0;g<y;++g)c+=f(u,n(v[g]),n(d[g])-n(v[g]),a),g<y-1&&(c+=", ");c+=");"}c&&l.set("transform",c),l._transform=i},get:function(t){var n=t._node,s=n.matrix,o=t.get("to")||{},u=t.get("to").transform,a=n.get("transform"),f=e.MatrixUtil.getTransformArray(u),l=a?e.MatrixUtil.getTransformArray(a):null,c,h,p,d,v;if(f)if(!l||l.length<1){l=[],p=f.length;for(h=0;h<p;++h)d=f[h][0],l[h]=e.MatrixUtil.getTransformFunctionArray(d);r=f,v=l}else if(e.MatrixUtil.compareTransformSequence(f,l))r=f,v=l;else{c=new e.Matrix,p=f.length;for(h=0;h<p;++h)d=f[h].shift(),d=d=="matrix"?"multiply":d,c[d].apply(c,f[h]);r=c.decompose(),v=s.decompose()}return i=u,v}}},"3.7.3",{requires:["anim-base","anim-easing","anim-color","matrix"]});
diff --git a/js/yui3/anim-xy/anim-xy-min.js b/js/yui3/anim-xy/anim-xy-min.js
new file mode 100644
index 000000000..d22888946
--- /dev/null
+++ b/js/yui3/anim-xy/anim-xy-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("anim-xy",function(e,t){var n=Number;e.Anim.behaviors.xy={set:function(e,t,r,i,s,o,u){e._node.setXY([u(s,n(r[0]),n(i[0])-n(r[0]),o),u(s,n(r[1]),n(i[1])-n(r[1]),o)])},get:function(e){return e._node.getXY()}}},"3.7.3",{requires:["anim-base","node-screen"]});
diff --git a/js/yui3/app-base/app-base-min.js b/js/yui3/app-base/app-base-min.js
new file mode 100644
index 000000000..4dea9673e
--- /dev/null
+++ b/js/yui3/app-base/app-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("app-base",function(e,t){var n=e.Lang,r=e.Object,i=e.PjaxBase,s=e.Router,o=e.View,u=e.ClassNameManager.getClassName,a=e.config.win,f;f=e.Base.create("app",e.Base,[o,s,i],{views:{},initializer:function(t){function i(t,r){n[r]=e.merge(n[r],t)}t||(t={});var n={};r.each(this.views,i),r.each(t.views,i),this.views=n,this._viewInfoMap={},this.after("activeViewChange",e.bind("_afterActiveViewChange",this)),this.get("serverRouting")||this._pjaxBindUI()},createView:function(t,i){var s=this.getViewInfo(t),u=s&&s.type||o,a,f;return a=n.isString(u)?r.getValue(e,u.split(".")):u,f=new a(i),this._viewInfoMap[e.stamp(f,!0)]=s,f},getViewInfo:function(t){return n.isString(t)?this.views[t]:t&&this._viewInfoMap[e.stamp(t,!0)]},render:function(){var t=e.App.CLASS_NAMES,n=this.get("container"),r=this.get("viewContainer"),i=this.get("activeView"),s=i&&i.get("container"),o=n.compareTo(r);return n.addClass(t.app),r.addClass(t.views),i&&!r.contains(s)&&r.appendChild(s),!n.contains(r)&&!o&&n.appendChild(r),this},showView:function(t,r,i,s){var o,u;return i||(i={}),s?i=e.merge(i,{callback:s}):n.isFunction(i)&&(i={callback:i}),n.isString(t)&&(o=this.getViewInfo(t),o&&o.preserve&&o.instance?(t=o.instance,this._viewInfoMap[e.stamp(t,!0)]=o):(t=this.createView(t,r),u=!0)),i.update&&!u&&t.setAttrs(r),"render"in i?i.render&&t.render():u&&t.render(),this._set("activeView",t,{options:i})},_attachView:function(e,t){if(!e)return;var n=this.getViewInfo(e),r=this.get("viewContainer");e.addTarget(this),n&&(n.instance=e),r[t?"prepend":"append"](e.get("container"))},_destroyContainer:function(){var t=e.App.CLASS_NAMES,n=this.get("container"),r=this.get("viewContainer"),i=n.compareTo(r);if(e.one("body").compareTo(n)){this.detachEvents(),n.removeClass(t.app),i?n.removeClass(t.views):r.remove(!0);return}r.remove(!0),i||n.remove(!0)},_detachView:function(t){if(!t)return;var n=this.getViewInfo(t)||{};n.preserve?t.remove():(t.destroy({remove:!0}),delete this._viewInfoMap[e.stamp(t,!0)],t===n.instance&&delete n.instance),t.removeTarget(this)},_getViewContainer:function(e){return!e&&!this._viewContainer&&(e=this._viewContainer=this.create(),this._set("viewContainer",e)),e},_initHtml5:function(){return this.get("serverRouting")===!1?!1:s.html5},_isChildView:function(e,t){var n=this.getViewInfo(e),r=this.getViewInfo(t);return n&&r?this.getViewInfo(n.parent)===r:!1},_isParentView:function(e,t){var n=this.getViewInfo(e),r=this.getViewInfo(t);return n&&r?this.getViewInfo(r.parent)===n:!1},_navigate:function(t,n){return this.get("serverRouting")||(n=e.merge({force:!0},n)),i.prototype._navigate.call(this,t,n)},_save:function(t,n){var r;return this.get("serverRouting")&&!this.get("html5")?this._hasSameOrigin(t)?(a&&(r=this._joinURL(t||""),n?a.location.replace(r):a.location=r),this):(e.error("Security error: The new URL must be of the same origin as the current URL."),this):s.prototype._save.apply(this,arguments)},_uiSetActiveView:function(e,t,n){n||(n={});var r=n.callback,i=this._isChildView(e,t),s=!i&&this._isParentView(e,t),o=!!n.prepend||s;if(e===t)return r&&r.call(this,e);this._attachView(e,o),this._detachView(t),r&&r.call(this,e)},_afterActiveViewChange:function(e){this._uiSetActiveView(e.newVal,e.prevVal,e.options)}},{ATTRS:{activeView:{value:null,readOnly:!0},container:{valueFn:function(){return e.one("body")}},html5:{valueFn:"_initHtml5"},linkSelector:{value:"a"},serverRouting:{valueFn:function(){return e.App.serverRouting},writeOnce:"initOnly"},viewContainer:{getter:"_getViewContainer",setter:e.one,writeOnce:!0}},_NON_ATTRS_CFG:["views"]}),e.namespace("App").Base=f,e.App=e.mix(e.Base.create("app",f,[]),e.App,!0),e.App.CLASS_NAMES={app:u("app"),views:u("app","views")}},"3.7.3",{requires:["classnamemanager","pjax-base","router","view"]});
diff --git a/js/yui3/app-content/app-content-min.js b/js/yui3/app-content/app-content-min.js
new file mode 100644
index 000000000..c50bb0347
--- /dev/null
+++ b/js/yui3/app-content/app-content-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("app-content",function(e,t){function r(){n.apply(this,arguments)}var n=e.PjaxContent;r.route=["loadContent","_contentRoute"],r.prototype={showContent:function(t,n,r){t=e.one(t),typeof n=="function"&&(n={callback:n},r=null),n=e.merge({render:!1},n);var i=n.view||"",s=typeof i=="string"?i:i.name,o=typeof i!="string"?i.config:{},u=this.getViewInfo(s),a,f,l,c;return delete n.view,t&&t.isFragment()&&t.get("childNodes").size()===1&&(t=t.get("firstChild")),t&&t.get("nodeType")===1?a=t:(l=u&&u.type||e.View,c=typeof l=="string"?e.Object.getValue(e,l.split(".")):l,f=c.prototype.containerTemplate,a=e.Node.create(f),a.append(t)),o=e.merge(o,{container:a}),this.showView(s,o,n,r)},_contentRoute:function(t,n,r){var i=n.content,s=e.config.doc,o;if(!i||!i.node)return r();i.title&&s&&(o=this.onceAfter("activeViewChange",function(){s.title=i.title})),this.showContent(i.node),o&&o.detach(),r()}},e.mix(r,n),e.mix(r,n,!1,null,1),e.App.Content=r,e.Base.mix(e.App,[r])},"3.7.3",{requires:["app-base","pjax-content"]});
diff --git a/js/yui3/app-transitions-css/app-transitions-css-min.css b/js/yui3/app-transitions-css/app-transitions-css-min.css
new file mode 100644
index 000000000..0f554291e
--- /dev/null
+++ b/js/yui3/app-transitions-css/app-transitions-css-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-app-transitioning .yui3-app-views,.yui3-app-views.yui3-app-transitioning{overflow-x:hidden;position:relative;white-space:nowrap;letter-spacing:-0.31em;word-spacing:-0.43em}.yui3-app-transitioning .yui3-app-views>*,.yui3-app-views.yui3-app-transitioning>*{display:inline-block;width:100%;vertical-align:top;white-space:normal;letter-spacing:normal;word-spacing:normal;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#yui3-css-stamp.app-transitions-css{display:none}
diff --git a/js/yui3/app-transitions-css/app-transitions-css.css b/js/yui3/app-transitions-css/app-transitions-css.css
new file mode 100644
index 000000000..adb179ffc
--- /dev/null
+++ b/js/yui3/app-transitions-css/app-transitions-css.css
@@ -0,0 +1,29 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-app-transitioning .yui3-app-views,
+.yui3-app-views.yui3-app-transitioning {
+ overflow-x: hidden;
+ position: relative;
+ white-space: nowrap;
+ letter-spacing: -0.31em; /* webkit: collapse white-space between units */
+ word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
+}
+.yui3-app-transitioning .yui3-app-views > *,
+.yui3-app-views.yui3-app-transitioning > * {
+ display: inline-block;
+ width: 100%;
+ vertical-align: top;
+ white-space: normal;
+ letter-spacing: normal;
+ word-spacing: normal;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.app-transitions-css { display: none; }
diff --git a/js/yui3/app-transitions-native/app-transitions-native-min.js b/js/yui3/app-transitions-native/app-transitions-native-min.js
new file mode 100644
index 000000000..eaf2f7d72
--- /dev/null
+++ b/js/yui3/app-transitions-native/app-transitions-native-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("app-transitions-native",function(e,t){function r(){}var n=e.App.Transitions;r.prototype={initializer:function(){this._transitioning=!1,this._viewTransitionQueue=[],e.Do.before(this._queueActiveView,this,"_uiSetActiveView")},_dequeueActiveView:function(){var t=this._viewTransitionQueue,n=t.shift(),r;n&&(t.length&&(r=e.merge(n[2],{transition:!1}),n.splice(2,1,r)),this._uiTransitionActiveView.apply(this,n))},_getFx:function(e,t,r){var i=n.FX,s=this.get("transitions");return r===!1||!s?null:r?i[r]:this._isChildView(e,t)?i[s.toChild]:this._isParentView(e,t)?i[s.toParent]:i[s.navigate]},_queueActiveView:function(){var t=e.Array(arguments,0,!0);return this._viewTransitionQueue.push(t),this._transitioning||this._dequeueActiveView(),new e.Do.Prevent},_uiTransitionActiveView:function(t,n,r){function p(){return this._detachView(n),s.removeClass(o),i&&i.call(this,t),this._transitioning=!1,this._dequeueActiveView()}r||(r={});var i=r.callback,s,o,u,a,f,l,c,h;if(t===n)return i&&i.call(this,t),this._transitioning=!1,this._dequeueActiveView();l=this._getFx(t,n,r.transition),u=this._isChildView(t,n),a=!u&&this._isParentView(t,n),f=!!r.prepend||a;if(!l)return this._attachView(t,f),this._detachView(n),i&&i.call(this,t),this._transitioning=!1,this._dequeueActiveView();this._transitioning=!0,s=this.get("container"),o=e.App.CLASS_NAMES.transitioning,s.addClass(o),this._attachView(t,f),h=new e.Parallel({context:this}),c={crossView:!!n&&!!t,prepended:f},t&&l.viewIn&&t.get("container").transition(l.viewIn,c,h.add()),n&&l.viewOut&&n.get("container").transition(l.viewOut,c,h.add()),h.done(p)}},e.mix(e.Transition.fx,{"app:fadeIn":{opacity:1,duration:.3,on:{start:function(e){var t={opacity:0},n=e.config;n.crossView&&!n.prepended&&(t.transform="translateX(-100%)"),this.setStyles(t)},end:function(){this.setStyle("transform","translateX(0)")}}},"app:fadeOut":{opacity:0,duration:.3,on:{start:function(e){var t={opacity:1},n=e.config;n.crossView&&n.prepended&&(t.transform="translateX(-100%)"),this.setStyles(t)},end:function(){this.setStyle("transform","translateX(0)")}}},"app:slideLeft":{duration:.3,transform:"translateX(-100%)",on:{start:function(){this.setStyles({opacity:1,transform:"translateX(0%)"})},end:function(){this.setStyle("transform","translateX(0)")}}},"app:slideRight":{duration:.3,transform:"translateX(0)",on:{start:function(){this.setStyles({opacity:1,transform:"translateX(-100%)"})},end:function(){this.setStyle("transform","translateX(0)")}}}}),e.App.TransitionsNative=r,e.Base.mix(e.App,[r])},"3.7.3",{requires:["app-transitions","app-transitions-css","parallel","transition"]});
diff --git a/js/yui3/app-transitions/app-transitions-min.js b/js/yui3/app-transitions/app-transitions-min.js
new file mode 100644
index 000000000..c582a6b2e
--- /dev/null
+++ b/js/yui3/app-transitions/app-transitions-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("app-transitions",function(e,t){function n(){}n.ATTRS={transitions:{setter:"_setTransitions",value:!1}},n.FX={fade:{viewIn:"app:fadeIn",viewOut:"app:fadeOut"},slideLeft:{viewIn:"app:slideLeft",viewOut:"app:slideLeft"},slideRight:{viewIn:"app:slideRight",viewOut:"app:slideRight"}},n.prototype={transitions:{navigate:"fade",toChild:"slideLeft",toParent:"slideRight"},_setTransitions:function(t){var n=this.transitions;return t&&t===!0?e.merge(n):t}},e.App.Transitions=n,e.Base.mix(e.App,[n]),e.mix(e.App.CLASS_NAMES,{transitioning:e.ClassNameManager.getClassName("app","transitioning")})},"3.7.3",{requires:["app-base"]});
diff --git a/js/yui3/array-extras/array-extras-min.js b/js/yui3/array-extras/array-extras-min.js
new file mode 100644
index 000000000..031b9903a
--- /dev/null
+++ b/js/yui3/array-extras/array-extras-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("array-extras",function(e,t){var n=e.Array,r=e.Lang,i=Array.prototype;n.lastIndexOf=r._isNative(i.lastIndexOf)?function(e,t,n){return n||n===0?e.lastIndexOf(t,n):e.lastIndexOf(t)}:function(e,t,n){var r=e.length,i=r-1;if(n||n===0)i=Math.min(n<0?r+n:n,r);if(i>-1&&r>0)for(;i>-1;--i)if(i in e&&e[i]===t)return i;return-1},n.unique=function(e,t){var n=0,r=e.length,i=[],s,o,u,a;e:for(;n<r;n++){a=e[n];for(s=0,u=i.length;s<u;s++){o=i[s];if(t){if(t.call(e,a,o,n,e))continue e}else if(a===o)continue e}i.push(a)}return i},n.filter=r._isNative(i.filter)?function(e,t,n){return i.filter.call(e,t,n)}:function(e,t,n){var r=0,i=e.length,s=[],o;for(;r<i;++r)r in e&&(o=e[r],t.call(n,o,r,e)&&s.push(o));return s},n.reject=function(e,t,r){return n.filter(e,function(e,n,i){return!t.call(r,e,n,i)})},n.every=r._isNative(i.every)?function(e,t,n){return i.every.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&!t.call(n,e[r],r,e))return!1;return!0},n.map=r._isNative(i.map)?function(e,t,n){return i.map.call(e,t,n)}:function(e,t,n){var r=0,s=e.length,o=i.concat.call(e);for(;r<s;++r)r in e&&(o[r]=t.call(n,e[r],r,e));return o},n.reduce=r._isNative(i.reduce)?function(e,t,n,r){return i.reduce.call(e,function(e,t,i,s){return n.call(r,e,t,i,s)},t)}:function(e,t,n,r){var i=0,s=e.length,o=t;for(;i<s;++i)i in e&&(o=n.call(r,o,e[i],i,e));return o},n.find=function(e,t,n){for(var r=0,i=e.length;r<i;r++)if(r in e&&t.call(n,e[r],r,e))return e[r];return null},n.grep=function(e,t){return n.filter(e,function(e,n){return t.test(e)})},n.partition=function(e,t,r){var i={matches:[],rejects:[]};return n.each(e,function(n,s){var u=t.call(r,n,s,e)?i.matches:i.rejects;u.push(n)}),i},n.zip=function(e,t){var r=[];return n.each(e,function(e,n){r.push([e,t[n]])}),r},n.flatten=function(e){var t=[],i,s,o;if(!e)return t;for(i=0,s=e.length;i<s;++i)o=e[i],r.isArray(o)?t.push.apply(t,n.flatten(o)):t.push(o);return t}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/array-invoke/array-invoke-min.js b/js/yui3/array-invoke/array-invoke-min.js
new file mode 100644
index 000000000..21afa425a
--- /dev/null
+++ b/js/yui3/array-invoke/array-invoke-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("array-invoke",function(e,t){e.Array.invoke=function(t,n){var r=e.Array(arguments,2,!0),i=e.Lang.isFunction,s=[];return e.Array.each(e.Array(t),function(e,t){e&&i(e[n])&&(s[t]=e[n].apply(e,r))}),s}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/arraylist-add/arraylist-add-min.js b/js/yui3/arraylist-add/arraylist-add-min.js
new file mode 100644
index 000000000..1f5cd97a6
--- /dev/null
+++ b/js/yui3/arraylist-add/arraylist-add-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("arraylist-add",function(e,t){e.mix(e.ArrayList.prototype,{add:function(t,n){var r=this._items;return e.Lang.isNumber(n)?r.splice(n,0,t):r.push(t),this},remove:function(e,t,n){n=n||this.itemsAreEqual;for(var r=this._items.length-1;r>=0;--r)if(n.call(this,e,this.item(r))){this._items.splice(r,1);if(!t)break}return this},itemsAreEqual:function(e,t){return e===t}})},"3.7.3",{requires:["arraylist"]});
diff --git a/js/yui3/arraylist-filter/arraylist-filter-min.js b/js/yui3/arraylist-filter/arraylist-filter-min.js
new file mode 100644
index 000000000..bbf84a284
--- /dev/null
+++ b/js/yui3/arraylist-filter/arraylist-filter-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("arraylist-filter",function(e,t){e.mix(e.ArrayList.prototype,{filter:function(t){var n=[];return e.Array.each(this._items,function(e,r){e=this.item(r),t(e)&&n.push(e)},this),new this.constructor(n)}})},"3.7.3",{requires:["arraylist"]});
diff --git a/js/yui3/arraylist/arraylist-min.js b/js/yui3/arraylist/arraylist-min.js
new file mode 100644
index 000000000..b395b9cb3
--- /dev/null
+++ b/js/yui3/arraylist/arraylist-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("arraylist",function(e,t){function s(t){t!==undefined?this._items=e.Lang.isArray(t)?t:n(t):this._items=this._items||[]}var n=e.Array,r=n.each,i;i={item:function(e){return this._items[e]},each:function(e,t){return r(this._items,function(n,r){n=this.item(r),e.call(t||n,n,r,this)},this),this},some:function(e,t){return n.some(this._items,function(n,r){return n=this.item(r),e.call(t||n,n,r,this)},this)},indexOf:function(e){return n.indexOf(this._items,e)},size:function(){return this._items.length},isEmpty:function(){return!this.size()},toJSON:function(){return this._items}},i._item=i.item,e.mix(s.prototype,i),e.mix(s,{addMethod:function(e,t){t=n(t),r(t,function(t){e[t]=function(){var e=n(arguments,0,!0),i=[];return r(this._items,function(n,r){n=this._item(r);var s=n[t].apply(n,e);s!==undefined&&s!==n&&(i[r]=s)},this),i.length?i:this}})}}),e.ArrayList=s},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/arraysort/arraysort-min.js b/js/yui3/arraysort/arraysort-min.js
new file mode 100644
index 000000000..a3c9c7dfa
--- /dev/null
+++ b/js/yui3/arraysort/arraysort-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("arraysort",function(e,t){var n=e.Lang,r=n.isValue,i=n.isString;e.ArraySort={compare:function(e,t,n){return r(e)?r(t)?(i(e)&&(e=e.toLowerCase()),i(t)&&(t=t.toLowerCase()),e<t?n?1:-1:e>t?n?-1:1:0):-1:r(t)?1:0}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/assets/skins/sam/arrows.png b/js/yui3/assets/skins/sam/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/assets/skins/sam/arrows.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/autocomplete-list.css b/js/yui3/assets/skins/sam/autocomplete-list.css
new file mode 100644
index 000000000..68b350911
--- /dev/null
+++ b/js/yui3/assets/skins/sam/autocomplete-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-aclist{position:absolute;z-index:1}.yui3-aclist-hidden{visibility:hidden}.yui3-aclist-aria{left:-9999px;position:absolute}.yui3-aclist-list{list-style:none;margin:0;overflow:hidden;padding:0}.yui3-aclist-item{cursor:pointer;list-style:none;padding:2px 5px}.yui3-aclist-item-active{outline:#afafaf dotted thin}.yui3-skin-sam .yui3-aclist-content{background:#fff;border:1px solid #afafaf;-moz-box-shadow:1px 1px 4px rgba(0,0,0,0.58);-webkit-box-shadow:1px 1px 4px rgba(0,0,0,0.58);box-shadow:1px 1px 4px rgba(0,0,0,0.58)}.yui3-skin-sam .yui3-aclist-item-hover{background:#bfdaff}.yui3-skin-sam .yui3-aclist-item-active{background:#2647a0;color:#fff;outline:0}#yui3-css-stamp.skin-sam-autocomplete-list{display:none}
diff --git a/js/yui3/assets/skins/sam/bg.png b/js/yui3/assets/skins/sam/bg.png
new file mode 100644
index 000000000..fd11e03de
--- /dev/null
+++ b/js/yui3/assets/skins/sam/bg.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/calendar-base.css b/js/yui3/assets/skins/sam/calendar-base.css
new file mode 100644
index 000000000..e24474df6
--- /dev/null
+++ b/js/yui3/assets/skins/sam/calendar-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-pane{width:100%}.yui3-calendar-grid{width:100%}.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-skin-sam .yui3-calendar-content{padding:10px;color:#000;border:1px solid gray;background:#f2f2f2;background:-moz-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f9f9f9),color-stop(100%,#f2f2f2));background:-webkit-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-o-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-ms-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9',endColorstr='#f2f2f2',GradientType=0);background:linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);-moz-border-radius:5px;border-radius:5px}.yui3-skin-sam .yui3-calendar-grid{padding:5px;border-collapse:collapse}.yui3-skin-sam .yui3-calendar-header{padding-bottom:10px}.yui3-skin-sam .yui3-calendar-header-label{margin:0;font-size:1em;font-weight:bold}.yui3-skin-sam .yui3-calendar-day,.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{padding:5px;border:1px solid #ccc;background:#fff;text-align:center}.yui3-skin-sam .yui3-calendar-day:hover{background:#06c;color:#fff}.yui3-skin-sam .yui3-calendar-selection-disabled,.yui3-skin-sam .yui3-calendar-selection-disabled:hover{color:#a6a6a6;background:#ccc}.yui3-skin-sam .yui3-calendar-weekday{font-weight:bold}.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{color:#a6a6a6}.yui3-skin-sam .yui3-calendar-day{font-weight:bold}.yui3-skin-sam .yui3-calendar-day-selected{background-color:#b3d4ff;color:#000}.yui3-skin-sam .yui3-calendar-header-label{text-align:center}.yui3-skin-sam .yui3-calendar-left-grid{margin-right:1em}.yui3-skin-sam .yui3-calendar-right-grid{margin-left:1em}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar-base{display:none}
diff --git a/js/yui3/assets/skins/sam/calendar.css b/js/yui3/assets/skins/sam/calendar.css
new file mode 100644
index 000000000..b85758568
--- /dev/null
+++ b/js/yui3/assets/skins/sam/calendar.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-calendar-day{cursor:pointer}.yui3-calendar-selection-disabled{cursor:default}.yui3-calendar-prevmonth-day{cursor:default}.yui3-calendar-nextmonth-day{cursor:default}.yui3-calendar-content:hover .yui3-calendar-day,.yui3-calendar-content:hover .yui3-calendar-prevmonth-day,.yui3-calendar-content:hover .yui3-calendar-nextmonth-day{-moz-user-select:none}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar{display:none}
diff --git a/js/yui3/assets/skins/sam/calendarnavigator.css b/js/yui3/assets/skins/sam/calendarnavigator.css
new file mode 100644
index 000000000..0c1039113
--- /dev/null
+++ b/js/yui3/assets/skins/sam/calendarnavigator.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-header{padding-left:15px;padding-right:15px}.yui3-calendar-header-label{width:100%}.yui3-calendarnav-prevmonth{cursor:pointer}.yui3-calendarnav-nextmonth{cursor:pointer}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth{color:#000;width:12px;height:14px;background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKNJREFUeNpiYCAeSAPxUiiWZqAi4ATiaiD+DMT/ofgzVIyTUsMDgfghksHo+CFUDcnAAIgP4DEYHR+A6iEIhIB4GgkGo+NpUDMwADMQFwHxBwoMh+EPULOYYYZ7APFVKhiMjkFmejBBLWFjoD5gQ+dQO4iwOloUiOdQYPgcqBkDl0zRQRQRGS2KGkVFHRB/QzL4G1SMk5qpQg6psJMjVhNAgAEAH+qPqeiPEUsAAAAASUVORK5CYII=);background-repeat:no-repeat}.yui3-skin-sam .yui3-calendarnav-prevmonth:hover,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPpJREFUeNpi/P//PwMxQD9jszSQ6oJyyy7O8H1KjD5GQhYADeYEUkVAXAHEPFDhL0DcAcR9QIu+k20B0PBAIDUBiOVwKHkExAVAS9aTZAHQYAOowfYMxIGDUIsu4LUAaLAQkGoB4kwG8sB0IK4BWvQOxQKgwcxAdj4Q1wExPwNl4CMQNwHxRKBFfxn10jd5ADm9QKzFQF1wDYiLmaAcNgbqA7CZTEBv7ADS2iDboN5joEIQgczSBpmNHsmiQKodiJPJNHwuEFcCDX49MMkUi0VRUB/hy2ggFy+jtKgohRYVnFDh79CiopuiogLNIjmobxigrn5EjD6AAAMAok9vhfHG8wQAAAAASUVORK5CYII=);color:#06c}.yui3-skin-sam .yui3-calendarnav-month-disabled,.yui3-skin-sam .yui3-calendarnav-month-disabled:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQhJREFUeNqs0yGLAlEUhuHrKoIgCFbBJghb3F+g0WrVarEqLIhBEEFYWKNNMBktU4z6C5RNkwyCyWQSTPuOfCOCrHNnxwMPyOGe73DAiTmOYywrhy/9/sTBZujN4k0KPbioi6teKuqCmsKGSN/10+q5ehN6QQkrLJB/Mp/Xm5VmAhdkMcEGZWNfZc1MlPGwII42dmiZ/1dLGW1lXhdU8YNvZEz0yijLy6z6FyTN6yvpX7DEOzo4vSD4pCwvc+lfcMEYBUwjhE+VMVbmw7/oiCY+sA4RvNZMUxmB38EWFTSwfxK815uKZkJ/yXMU0cf5rn9Wr6g3f1bC4nwvbIAZRup1Ay671a8AAwC3OzOqxK+rkwAAAABJRU5ErkJggg==);cursor:default;color:#ccc}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-prevmonth:hover{background-position:0 0;margin-left:-12px}.yui3-skin-sam .yui3-calendarnav-nextmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background-position:-12px 0;margin-right:-12px}.yui3-skin-sam .yui3-calendarnav-prevmonth span,.yui3-skin-sam .yui3-calendarnav-nextmonth span{display:none;*display:block}#yui3-css-stamp.skin-sam-calendarnavigator{display:none}
diff --git a/js/yui3/assets/skins/sam/console-filters.css b/js/yui3/assets/skins/sam/console-filters.css
new file mode 100644
index 000000000..69b6a580d
--- /dev/null
+++ b/js/yui3/assets/skins/sam/console-filters.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{text-align:left;padding:5px 0;border:1px inset;margin:0 2px}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories{background:#fff;border-bottom:2px ridge}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{background:#fff;margin-bottom:2px;border-top:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-filter-label{white-space:nowrap;margin-left:1ex}#yui3-css-stamp.skin-sam-console-filters{display:none}
diff --git a/js/yui3/assets/skins/sam/console.css b/js/yui3/assets/skins/sam/console.css
new file mode 100644
index 000000000..5374c653e
--- /dev/null
+++ b/js/yui3/assets/skins/sam/console.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-console-separate{position:absolute;right:1em;top:1em;z-index:999}.yui3-skin-sam .yui3-console-inline{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:top}.yui3-skin-sam .yui3-console-inline .yui3-console-content{position:relative}.yui3-skin-sam .yui3-console-content{background:#777;_background:#d8d8da url(bg.png) repeat-x 0 0;font:normal 13px/1.3 Arial,sans-serif;text-align:left;border:1px solid #777;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-bd,.yui3-skin-sam .yui3-console-ft{position:relative}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-ft .yui3-console-controls{text-align:right}.yui3-skin-sam .yui3-console-hd{background:#d8d8da url(bg.png) repeat-x 0 0;padding:1ex;border:1px solid transparent;_border:0 none;border-top-right-radius:10px;border-top-left-radius:10px;-moz-border-radius-topright:10px;-moz-border-radius-topleft:10px;-webkit-border-top-right-radius:10px;-webkit-border-top-left-radius:10px}.yui3-skin-sam .yui3-console-bd{background:#fff;border-top:1px solid #777;border-bottom:1px solid #777;color:#000;font-size:11px;overflow:auto;overflow-x:auto;overflow-y:scroll;_width:100%}.yui3-skin-sam .yui3-console-ft{background:#d8d8da url(bg.png) repeat-x 0 0;border:1px solid transparent;_border:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-controls{padding:4px 1ex;zoom:1}.yui3-skin-sam .yui3-console-title{color:#000;display:inline;float:left;font-weight:bold;font-size:13px;height:24px;line-height:24px;margin:0;padding-left:1ex}.yui3-skin-sam .yui3-console-pause-label{float:left}.yui3-skin-sam .yui3-console-button{line-height:1.3}.yui3-skin-sam .yui3-console-collapsed .yui3-console-bd,.yui3-skin-sam .yui3-console-collapsed .yui3-console-ft{display:none}.yui3-skin-sam .yui3-console-content.yui3-console-collapsed{-webkit-border-radius:0}.yui3-skin-sam .yui3-console-collapsed .yui3-console-hd{border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:0}.yui3-skin-sam .yui3-console-entry{border-bottom:1px solid #aaa;min-height:32px;_height:32px}.yui3-skin-sam .yui3-console-entry-meta{margin:0;overflow:hidden}.yui3-skin-sam .yui3-console-entry-content{margin:0;padding:0 1ex;white-space:pre-wrap;word-wrap:break-word}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-src{color:#000;font-style:italic;font-weight:bold;float:right;margin:2px 5px 0 0}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-time{color:#777;padding-left:1ex}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-time{color:#555}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-meta .yui3-console-entry-cat{display:none}.yui3-skin-sam .yui3-console-entry-warn{background:#aee url(warn_error.png) no-repeat -15px 15px}.yui3-skin-sam .yui3-console-entry-error{background:#ffa url(warn_error.png) no-repeat 5px -24px;color:#900}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-content,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-content{padding-left:24px}.yui3-skin-sam .yui3-console-entry-cat{text-transform:uppercase;padding:1px 4px;background-color:#ccc}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-cat{background-color:#ac2}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-cat{background-color:#e81}.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-cat{background-color:#b00;color:#fff}.yui3-skin-sam .yui3-console-hidden{display:none}#yui3-css-stamp.skin-sam-console{display:none}
diff --git a/js/yui3/assets/skins/sam/datatable-base-deprecated.css b/js/yui3/assets/skins/sam/datatable-base-deprecated.css
new file mode 100644
index 000000000..5be172bc9
--- /dev/null
+++ b/js/yui3/assets/skins/sam/datatable-base-deprecated.css
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-datatable-mask{position:absolute;z-index:9500}.yui3-datatable-tmp{position:absolute;left:-9000px}.yui3-datatable-scrollable .yui3-datatable-bd{overflow:auto}.yui3-datatable-scrollable .yui3-datatable-hd{overflow:hidden;position:relative}.yui3-datatable-scrollable .yui3-datatable-bd thead tr,.yui3-datatable-scrollable .yui3-datatable-bd thead th{position:absolute;left:-1500px}.yui3-datatable-scrollable tbody{-moz-outline:0}.yui3-skin-sam thead .yui3-datatable-sortable{cursor:pointer}.yui3-skin-sam thead .yui3-datatable-draggable{cursor:move}.yui3-datatable-coltarget{position:absolute;z-index:999}.yui3-datatable-hd{zoom:1}th.yui3-datatable-resizeable .yui3-datatable-resizerliner{position:relative}.yui3-datatable-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui3-datatable-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui3-datatable-hidden .yui3-datatable-liner,td.yui3-datatable-hidden .yui3-datatable-liner,th.yui3-datatable-hidden .yui3-datatable-resizer{display:none}.yui3-datatable-editor,.yui3-datatable-editor-shim{position:absolute;z-index:9000}.yui3-skin-sam .yui3-datatable table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable thead{border-spacing:0}.yui3-skin-sam .yui3-datatable caption{color:#000;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable th{background:#d8d8da url(sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-datatable th,.yui3-skin-sam .yui3-datatable th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom}.yui3-skin-sam .yui3-datatable th{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable tr.yui3-datatable-first td{border-top:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable th .yui3-datatable-liner{white-space:nowrap}.yui3-skin-sam .yui3-datatable-liner{margin:0;padding:0;padding:4px 10px 4px 10px;overflow:visible;border:0 solid black}.yui3-skin-sam .yui3-datatable-coltarget{width:5px;background-color:red}.yui3-skin-sam .yui3-datatable td{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb;text-align:left}.yui3-skin-sam .yui3-datatable-list td{border-right:0}.yui3-skin-sam .yui3-datatable-resizer{width:6px}.yui3-skin-sam .yui3-datatable-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui3-skin-sam .yui3-datatable-message{background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable table{border:0}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-hd{border-left:1px solid #7f7f7f;border-top:1px solid #7f7f7f;border-right:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-bd{border-left:1px solid #7f7f7f;border-bottom:1px solid #7f7f7f;border-right:1px solid #7f7f7f;background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-data tr.yui3-datatable-last td{border-bottom:1px solid #7f7f7f}.yui3-skin-sam th.yui3-datatable-asc,.yui3-skin-sam th.yui3-datatable-desc{background:url(sprite.png) repeat-x 0 -100px}.yui3-skin-sam th.yui3-datatable-sortable .yui3-datatable-liner{padding-right:20px}.yui3-skin-sam th.yui3-datatable-asc .yui3-datatable-liner{background:url(dt-arrow-up.png) no-repeat right}.yui3-skin-sam th.yui3-datatable-desc .yui3-datatable-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui3-datatable-editable{cursor:pointer}.yui3-datatable-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui3-datatable-editor label{padding-left:4px;padding-right:6px}.yui3-datatable-editor .yui3-datatable-button{padding-top:6px;text-align:right}.yui3-datatable-editor .yui3-datatable-button button{background:url(sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui3-datatable-editor .yui3-datatable-button button.yui3-datatable-default{background:url(sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui3-datatable-editor .yui3-datatable-button button:hover{background:url(sprite.png) repeat-x 0 -1300px;color:#000}.yui3-datatable-editor .yui3-datatable-button button:active{background:url(sprite.png) repeat-x 0 -1700px;color:#000}.yui3-skin-sam .yui3-datatable td{background-color:transparent}.yui3-skin-sam tr.yui3-datatable-even td{background-color:#FFF}.yui3-skin-sam tr.yui3-datatable-odd td{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#dbeaff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam th.yui3-datatable-highlighted,.yui3-skin-sam th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam tr.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}
+.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}.yui3-skin-sam th.yui3-datatable-selected,.yui3-skin-sam th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam tr.yui3-datatable-selected td,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-paginator{display:block;margin:6px 0;white-space:nowrap}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-last,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-selected{padding:2px 6px}.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-last{text-decoration:none}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-previous,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-next{display:none}.yui3-skin-sam a.yui3-datatable-page{border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none;background-color:#fff}.yui3-skin-sam .yui3-datatable-selected{border:1px solid #fff;background-color:#fff}#yui3-css-stamp.skin-sam-datatable-base-deprecated{display:none}
diff --git a/js/yui3/assets/skins/sam/datatable-base.css b/js/yui3/assets/skins/sam/datatable-base.css
new file mode 100644
index 000000000..4947e3667
--- /dev/null
+++ b/js/yui3/assets/skins/sam/datatable-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-table{empty-cells:show}.yui3-skin-sam .yui3-datatable-table{margin:0;padding:0;font-family:arial,sans-serif;border-collapse:separate;border-spacing:0;border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable-cell,.yui3-skin-sam .yui3-datatable-header{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:4px 10px 4px 10px}.yui3-skin-sam .yui3-datatable-cell:first-child,.yui3-skin-sam .yui3-datatable-first-header{border-left-width:0}.yui3-skin-sam .yui3-datatable-header{background:#fff url(sprite.png) repeat-x 0 0;background-image:-webkit-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-moz-linear-gradient(top,transparent 40%,rgba(0,0,0,0.21));background-image:-ms-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-o-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:linear-gradient(transparent 40%,rgba(0,0,0,0.21));color:#000;font-weight:normal;text-align:left;text-shadow:0 1px 1px #fff;vertical-align:bottom;white-space:nowrap}.yui3-skin-sam .yui3-datatable-cell{background-color:transparent}.yui3-skin-sam .yui3-datatable-even .yui3-datatable-cell{background-color:#fff}.yui3-skin-sam .yui3-datatable-odd .yui3-datatable-cell{background-color:#edf5ff}#yui3-css-stamp.skin-sam-datatable-base{display:none}
diff --git a/js/yui3/assets/skins/sam/datatable-message.css b/js/yui3/assets/skins/sam/datatable-message.css
new file mode 100644
index 000000000..bc6ffee49
--- /dev/null
+++ b/js/yui3/assets/skins/sam/datatable-message.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-message{display:none}.yui3-datatable-message-visible .yui3-datatable-message{display:block;display:table-row-group}.yui3-skin-sam .yui3-datatable-message-content{border:0 none;border-bottom:1px solid #cbcbcb;padding:4px 10px}#yui3-css-stamp.skin-sam-datatable-message{display:none}
diff --git a/js/yui3/assets/skins/sam/datatable-scroll.css b/js/yui3/assets/skins/sam/datatable-scroll.css
new file mode 100644
index 000000000..13ba4e560
--- /dev/null
+++ b/js/yui3/assets/skins/sam/datatable-scroll.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-scrollable-x{_overflow-x:hidden;_position:relative}.yui3-datatable-scrollable-y,.yui3-datatable-scrollable-y .yui3-datatable-x-scroller{_overflow-y:hidden;_position:relative}.yui3-datatable-y-scroller-container{overflow-x:hidden;position:relative}.yui3-datatable-scrollable-y .yui3-datatable-content{position:relative}.yui3-datatable-scrollable-y .yui3-datatable-table .yui3-datatable-columns{visibility:hidden}.yui3-datatable-scroll-columns{position:absolute;width:100%;z-index:2}.yui3-datatable-y-scroller,.yui3-datatable-scrollable-x .yui3-datatable-caption-table{width:100%}.yui3-datatable-x-scroller{position:relative;overflow-x:scroll;overflow-y:hidden}.yui3-datatable-scrollable-y .yui3-datatable-y-scroller{position:relative;overflow-x:hidden;overflow-y:scroll;z-index:1;-webkit-overflow-scrolling:touch}.yui3-datatable-scrollbar{position:absolute;overflow-x:hidden;overflow-y:scroll;z-index:2}.yui3-datatable-scrollbar div{position:absolute;width:1px;visibility:hidden}.yui3-skin-sam .yui3-datatable-scroll-columns{border-collapse:separate;border-spacing:0;font-family:arial,sans-serif;margin:0;padding:0;top:0;left:0}.yui3-skin-sam .yui3-datatable-scroll-columns .yui3-datatable-header{padding:0}.yui3-skin-sam .yui3-datatable-x-scroller,.yui3-skin-sam .yui3-datatable-y-scroller-container{border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-scrollable-x .yui3-datatable-y-scroller-container,.yui3-skin-sam .yui3-datatable-x-scroller .yui3-datatable-table,.yui3-skin-sam .yui3-datatable-y-scroller .yui3-datatable-table{border:0 none}#yui3-css-stamp.skin-sam-datatable-scroll{display:none}
diff --git a/js/yui3/assets/skins/sam/datatable-sort.css b/js/yui3/assets/skins/sam/datatable-sort.css
new file mode 100644
index 000000000..c04017372
--- /dev/null
+++ b/js/yui3/assets/skins/sam/datatable-sort.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-sortable-column{z-index:1}.yui3-datatable-sortable-column:focus,.yui3-datatable-sortable-column:active{z-index:2}.yui3-skin-sam .yui3-datatable-sortable-column{cursor:pointer}.yui3-skin-sam .yui3-datatable-columns .yui3-datatable-sorted,.yui3-skin-sam .yui3-datatable-sortable-column:hover{*background:#c1c4c8 url(sprite.png) repeat-x 0 -100px;background-color:#f1f2f3}.yui3-skin-sam .yui3-datatable-sort-liner{display:block;height:100%;position:relative;padding-right:15px;position:relative}.yui3-skin-sam .yui3-datatable-sort-indicator{position:absolute;right:0;bottom:.5ex;width:7px;height:10px;background:url(sort-arrow-sprite.png) no-repeat 0 0;_background:url(sort-arrow-sprite-ie.png) no-repeat 0 0;overflow:hidden}.yui3-skin-sam .yui3-datatable-sorted .yui3-datatable-sort-indicator{background-position:0 -10px}.yui3-skin-sam .yui3-datatable-sorted-desc .yui3-datatable-sort-indicator{background-position:0 -20px}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted{background-color:#dbeaff}#yui3-css-stamp.skin-sam-datatable-sort{display:none}
diff --git a/js/yui3/assets/skins/sam/dial.css b/js/yui3/assets/skins/sam/dial.css
new file mode 100644
index 000000000..de135759e
--- /dev/null
+++ b/js/yui3/assets/skins/sam/dial.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+v\:oval,v\:shadow,v\:fill{behavior:url(#default#VML);display:inline-block;zoom:1;*display:inline}.yui3-dial{position:relative;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.yui3-dial-content,.yui3-dial-ring{position:relative}.yui3-dial-handle,.yui3-dial-marker,.yui3-dial-center-button,.yui3-dial-reset-string,.yui3-dial-handle-vml,.yui3-dial-marker-vml,.yui3-dial-center-button-vml,.yui3-dial-ring-vml v\:oval,.yui3-dial-center-button-vml v\:oval{position:absolute}.yui3-dial-center-button-vml v\:oval{font-size:1px;top:0;left:0}.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden v\:oval,.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden{opacity:0;filter:alpha(opacity=0)}.yui3-skin-sam .yui3-dial-handle{background:#6c3a3a;opacity:.3;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;cursor:pointer;font-size:1px}.yui3-skin-sam .yui3-dial-ring{background:#bebdb7;background:-moz-linear-gradient(100% 100% 135deg,#7b7a6d,#fff);background:-webkit-gradient(linear,left top,right bottom,from(#fff),to(#7b7a6d));box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-webkit-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-moz-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset}.yui3-skin-sam .yui3-dial-center-button{box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);-moz-box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);background:#dddbd4;background:-moz-radial-gradient(30% 30% 0deg,circle farthest-side,#fbfbf9 24%,#f2f0ea 41%,#d3d0c3 83%) repeat scroll 0 0 transparent;background:-webkit-gradient(radial,15 15,15,30 30,40,from(#fbfbf9),to(#d3d0c3),color-stop(.2,#f2f0ea));cursor:pointer;opacity:.7}.yui3-skin-sam .yui3-dial-reset-string{color:#676767;font-size:85%;text-decoration:underline}.yui3-skin-sam .yui3-dial-label{color:#808080;margin-bottom:.8em}.yui3-skin-sam .yui3-dial-value-string{margin-left:.5em;color:#000;font-size:130%}.yui3-skin-sam .yui3-dial-value{visibility:hidden;position:absolute;top:0;left:102%;width:4em}.yui3-skin-sam .yui3-dial-north-mark{position:absolute;border-left:2px solid #ccc;height:5px;width:10px;left:50%;top:-7px;font-size:1px}.yui3-skin-sam .yui3-dial-marker{background-color:#000;opacity:.2;font-size:1px}.yui3-skin-sam .yui3-dial-marker-max-min{background-color:#ab3232;opacity:.6}.yui3-skin-sam .yui3-dial-ring-vml,.yui3-skin-sam .yui3-dial-center-button-vml,.yui3-skin-sam .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam .yui3-dial-marker-vml,.yui3-skin-sam .yui3-dial-handle-vml{background:0;opacity:1}#yui3-css-stamp.skin-sam-dial{display:none}
diff --git a/js/yui3/assets/skins/sam/dt-arrow-dn.png b/js/yui3/assets/skins/sam/dt-arrow-dn.png
new file mode 100644
index 000000000..9c42b8331
--- /dev/null
+++ b/js/yui3/assets/skins/sam/dt-arrow-dn.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/dt-arrow-up.png b/js/yui3/assets/skins/sam/dt-arrow-up.png
new file mode 100644
index 000000000..07e237512
--- /dev/null
+++ b/js/yui3/assets/skins/sam/dt-arrow-up.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/horizontal-menu-submenu-indicator.png b/js/yui3/assets/skins/sam/horizontal-menu-submenu-indicator.png
new file mode 100644
index 000000000..a2482ac79
--- /dev/null
+++ b/js/yui3/assets/skins/sam/horizontal-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/horizontal-menu-submenu-toggle.png b/js/yui3/assets/skins/sam/horizontal-menu-submenu-toggle.png
new file mode 100644
index 000000000..4379f817d
--- /dev/null
+++ b/js/yui3/assets/skins/sam/horizontal-menu-submenu-toggle.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/node-flick.css b/js/yui3/assets/skins/sam/node-flick.css
new file mode 100644
index 000000000..30020432b
--- /dev/null
+++ b/js/yui3/assets/skins/sam/node-flick.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-flick{position:relative;overflow:hidden}.yui3-flick-content{position:relative}#yui3-css-stamp.skin-sam-node-flick{display:none}
diff --git a/js/yui3/assets/skins/sam/node-menunav.css b/js/yui3/assets/skins/sam/node-menunav.css
new file mode 100644
index 000000000..2ce64e5c3
--- /dev/null
+++ b/js/yui3/assets/skins/sam/node-menunav.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-menu .yui3-menu{position:absolute;z-index:1}.yui3-menu .yui3-shim{position:absolute;top:0;left:0;z-index:-1;opacity:0;filter:alpha(opacity=0);border:0;margin:0;padding:0;height:100%;width:100%}.yui3-menu-hidden{top:-10000px;left:-10000px;visibility:hidden}.yui3-menu li{list-style-type:none}.yui3-menu ul,.yui3-menu li{margin:0;padding:0}.yui3-menu-label,.yui3-menuitem-content{text-align:left;white-space:nowrap;display:block}.yui3-menu-horizontal li{float:left;width:auto}.yui3-menu-horizontal li li{float:none}.yui3-menu-horizontal ul{*zoom:1}.yui3-menu-horizontal ul ul{*zoom:normal}.yui3-menu-horizontal>.yui3-menu-content>ul:after{content:"";display:block;clear:both;line-height:0;font-size:0;visibility:hidden}.yui3-menu-content{*zoom:1}.yui3-menu-hidden .yui3-menu-content{*zoom:normal}.yui3-menuitem-content,.yui3-menu-label{_zoom:1}.yui3-menu-hidden .yui3-menuitem-content,.yui3-menu-hidden .yui3-menu-label{_zoom:normal}.yui3-skin-sam .yui3-menu-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:93%;line-height:1.5;*line-height:1.45;border:solid 1px #808080;background:#fff;padding:3px 0}.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:100%}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-content{line-height:2;*line-height:1.9;background:url(sprite.png) repeat-x 0 0;padding:0}.yui3-skin-sam .yui3-menu ul,.yui3-skin-sam .yui3-menu ul ul{margin-top:3px;padding-top:3px;border-top:solid 1px #ccc}.yui3-skin-sam .yui3-menu ul.first-of-type{border:0;margin:0;padding:0}.yui3-skin-sam .yui3-menu-horizontal ul{padding:0;margin:0;border:0}.yui3-skin-sam .yui3-menu li,.yui3-skin-sam .yui3-menu .yui3-menu li{_border-bottom:solid 1px #fff}.yui3-skin-sam .yui3-menu-horizontal li{_border-bottom:0}.yui3-skin-sam .yui3-menubuttonnav li{border-right:solid 1px #ccc}.yui3-skin-sam .yui3-splitbuttonnav li{border-right:solid 1px #808080}.yui3-skin-sam .yui3-menubuttonnav li li,.yui3-skin-sam .yui3-splitbuttonnav li li{border-right:0}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label,.yui3-skin-sam .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-content{padding:0 1em;color:#000;text-decoration:none;cursor:default;float:none;border:0;margin:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-content{padding:0 10px;border-style:solid;border-color:#808080;border-width:1px 0;margin:-1px 0;float:left;width:auto}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label{background:url(vertical-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label{background:url(sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{background-image:none}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label{padding-right:0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label em{font-style:normal;padding-right:20px;display:block;background:url(horizontal-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{padding:0}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label a{float:left;width:auto;color:#000;text-decoration:none;cursor:default;padding:0 5px 0 10px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label .yui3-menu-toggle{padding:0;border-left:solid 1px #ccc;width:15px;overflow:hidden;text-indent:-1000px;background:url(horizontal-menu-submenu-indicator.png) 3px center no-repeat}.yui3-skin-sam .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-active,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-menuvisible{background-color:#b3d4ff}.yui3-skin-sam .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content{background-image:none;background-color:#b3d4ff;border-left-width:0;margin-left:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-menuvisible{border-color:#7d98b8;background:url(sprite.png) repeat-x 0 -1700px}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-menubuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-left-width:1px;margin-left:-1px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-color:#808080;background:transparent}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible .yui3-menu-toggle{border-color:#7d98b8;background:url(horizontal-menu-submenu-toggle.png) left center no-repeat}#yui3-css-stamp.skin-sam-node-menunav{display:none}
diff --git a/js/yui3/assets/skins/sam/overlay.css b/js/yui3/assets/skins/sam/overlay.css
new file mode 100644
index 000000000..925769f7a
--- /dev/null
+++ b/js/yui3/assets/skins/sam/overlay.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-overlay{position:absolute}.yui3-overlay-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-overlay-content{overflow:hidden!important}#yui3-css-stamp.skin-sam-overlay{display:none}
diff --git a/js/yui3/assets/skins/sam/panel.css b/js/yui3/assets/skins/sam/panel.css
new file mode 100644
index 000000000..270c58294
--- /dev/null
+++ b/js/yui3/assets/skins/sam/panel.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-panel{position:absolute}.yui3-panel-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-panel-content{overflow:hidden!important}.yui3-panel .yui3-widget-hd{position:relative}.yui3-panel .yui3-widget-hd .yui3-widget-buttons{position:absolute;top:0;right:0}.yui3-panel .yui3-widget-ft .yui3-widget-buttons{display:inline-block;*display:inline;zoom:1}.yui3-skin-sam .yui3-panel-content{-webkit-box-shadow:0 0 5px #333;-moz-box-shadow:0 0 5px #333;box-shadow:0 0 5px #333;border:1px solid black;background:white}.yui3-skin-sam .yui3-panel .yui3-widget-hd{padding:8px 28px 8px 8px;min-height:13px;_height:13px;color:white;background-color:#3961c5;background:-moz-linear-gradient(0% 100% 90deg,#2647a0 7%,#3d67ce 50%,#426fd9 100%);background:-webkit-gradient(linear,left bottom,left top,from(#2647a0),color-stop(0.07,#2647a0),color-stop(0.5,#3d67ce),to(#426fd9))}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-widget-buttons{padding:8px}.yui3-skin-sam .yui3-panel .yui3-widget-bd{padding:10px}.yui3-skin-sam .yui3-panel .yui3-widget-ft{background:#edf5ff;padding:8px;text-align:right}.yui3-skin-sam .yui3-panel .yui3-widget-ft .yui3-button{margin-left:8px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close{background:transparent;filter:none;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;width:13px;height:13px;padding:0;overflow:hidden;vertical-align:top;*font-size:0;*line-height:0;*letter-spacing:-1000px;*color:#86a5ec;*background:url(sprite_icons.png) no-repeat 1px 1px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close:before{content:url(sprite_icons.png);display:inline-block;text-align:center;font-size:0;line-height:0;width:13px;margin:1px 0 0 1px}.yui3-skin-sam .yui3-panel-hidden .yui3-widget-hd .yui3-button-close{display:none}#yui3-css-stamp.skin-sam-panel{display:none}
diff --git a/js/yui3/assets/skins/sam/rail-x-lines.png b/js/yui3/assets/skins/sam/rail-x-lines.png
new file mode 100644
index 000000000..45c84288f
--- /dev/null
+++ b/js/yui3/assets/skins/sam/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/rail-x.png b/js/yui3/assets/skins/sam/rail-x.png
new file mode 100644
index 000000000..b99e1049e
--- /dev/null
+++ b/js/yui3/assets/skins/sam/rail-x.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/rail-y-lines.png b/js/yui3/assets/skins/sam/rail-y-lines.png
new file mode 100644
index 000000000..841c97088
--- /dev/null
+++ b/js/yui3/assets/skins/sam/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/rail-y.png b/js/yui3/assets/skins/sam/rail-y.png
new file mode 100644
index 000000000..2bec78ab6
--- /dev/null
+++ b/js/yui3/assets/skins/sam/rail-y.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/resize-base.css b/js/yui3/assets/skins/sam/resize-base.css
new file mode 100644
index 000000000..e915ab263
--- /dev/null
+++ b/js/yui3/assets/skins/sam/resize-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper{z-index:0;zoom:1}.yui3-resize-handle{position:absolute;display:block;z-index:100;zoom:1}.yui3-resize-proxy{position:absolute;border:1px dashed #000;position:absolute;z-index:10000}.yui3-resize-hidden-handles .yui3-resize-handle{opacity:0;filter:alpha(opacity=0)}.yui3-resize-handle-t,.yui3-resize-handle-b{width:100%;left:0;height:6px}.yui3-resize-handle-l,.yui3-resize-handle-r{height:100%;top:0;width:6px}.yui3-resize-handle-t{cursor:n-resize;top:0}.yui3-resize-handle-b{cursor:s-resize;bottom:0}.yui3-resize-handle-l{cursor:w-resize;left:0}.yui3-resize-handle-r{cursor:e-resize;right:0}.yui3-resize-handle-inner{position:absolute;zoom:1}@media only screen and (min-device-width :320px) and (max-device-width:480px){.yui3-resize-handle-inner:after{content:"";width:40px;height:40px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-12px;right:0}.yui3-resize-handle-inner-l:after{top:-12px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-12px}.yui3-resize-handle-inner-b:after{bottom:0;left:-12px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}@media only screen and (min-device-width :768px) and (max-device-width:1024px){.yui3-resize-handle-inner:after{content:"";width:30px;height:30px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-6px;right:0}.yui3-resize-handle-inner-l:after{top:-6px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-6px}.yui3-resize-handle-inner-b:after{bottom:0;left:-6px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b{margin-left:-8px;left:50%}.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-r{margin-top:-8px;top:50%}.yui3-resize-handle-inner-t{top:-4px}.yui3-resize-handle-inner-b{bottom:-4px}.yui3-resize-handle-inner-l{left:-4px}.yui3-resize-handle-inner-r{right:-4px}.yui3-resize-handle-tr,.yui3-resize-handle-br,.yui3-resize-handle-tl,.yui3-resize-handle-bl{height:15px;width:15px;z-index:200}.yui3-resize-handle-tr{cursor:ne-resize;top:0;right:0}.yui3-resize-handle-tl{cursor:nw-resize;top:0;left:0}.yui3-resize-handle-br{cursor:se-resize;bottom:0;right:0}.yui3-resize-handle-bl{cursor:sw-resize;bottom:0;left:0}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{background-repeat:no-repeat;background:url(arrows.png) no-repeat 0 0;display:block;height:15px;overflow:hidden;text-indent:-99999em;width:15px}.yui3-resize-handle-inner-br{background-position:-30px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tr{background-position:-58px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-bl{background-position:-75px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tl{background-position:-47px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t{background-position:-15px 0}#yui3-css-stamp.skin-sam-resize-base{display:none}
diff --git a/js/yui3/assets/skins/sam/scrollview-base.css b/js/yui3/assets/skins/sam/scrollview-base.css
new file mode 100644
index 000000000..15ea4d0aa
--- /dev/null
+++ b/js/yui3/assets/skins/sam/scrollview-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none}.yui3-scrollview-hidden{display:none}.yui3-scrollview-content{position:relative}.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}#yui3-css-stamp.skin-sam-scrollview-base{display:none}
diff --git a/js/yui3/assets/skins/sam/scrollview-list.css b/js/yui3/assets/skins/sam/scrollview-list.css
new file mode 100644
index 000000000..aad28c9af
--- /dev/null
+++ b/js/yui3/assets/skins/sam/scrollview-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}.yui3-skin-sam .yui3-scrollview{background-color:white}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{*zoom:1}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-list{*zoom:1;list-style:none;padding:0;margin:0}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content{border-top:0;background-color:white;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:black}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{border-bottom:1px solid #303030;padding:15px 20px 16px;font-size:100%;font-weight:bold;background-color:white;cursor:pointer}#yui3-css-stamp.skin-sam-scrollview-list{display:none}
diff --git a/js/yui3/assets/skins/sam/scrollview-scrollbars.css b/js/yui3/assets/skins/sam/scrollview-scrollbars.css
new file mode 100644
index 000000000..8a8332586
--- /dev/null
+++ b/js/yui3/assets/skins/sam/scrollview-scrollbars.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview-scrollbar{opacity:1;position:absolute;width:6px;height:10px}.yui3-scrollview-scrollbar{top:0;right:1px}.yui3-scrollview-scrollbar-horiz{top:auto;height:8px;width:20px;bottom:1px;left:0}.yui3-scrollview-scrollbar .yui3-scrollview-child{position:absolute;right:0;display:block;width:100%;height:4px}.yui3-scrollview-scrollbar .yui3-scrollview-first{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-last{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-middle{position:absolute;top:4px;height:1px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-child{display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline;top:0;left:0;bottom:auto;right:auto}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{width:4px;height:6px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{top:0;left:4px;width:1px;height:6px}.yui3-scrollview-scrollbar-vert-basic{height:auto}.yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child{position:static;_overflow:hidden;_line-height:4px}.yui3-scrollview-scrollbar-horiz-basic{width:auto;white-space:nowrap;line-height:6px;_overflow:hidden}.yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{position:static;padding:0;margin:0;top:auto;left:auto;right:auto;bottom:auto}.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none}#yui3-css-stamp.skin-sam-scrollview-scrollbars{display:none}
diff --git a/js/yui3/assets/skins/sam/skin.css b/js/yui3/assets/skins/sam/skin.css
new file mode 100644
index 000000000..912960c8b
--- /dev/null
+++ b/js/yui3/assets/skins/sam/skin.css
@@ -0,0 +1,34 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-aclist{position:absolute;z-index:1}.yui3-aclist-hidden{visibility:hidden}.yui3-aclist-aria{left:-9999px;position:absolute}.yui3-aclist-list{list-style:none;margin:0;overflow:hidden;padding:0}.yui3-aclist-item{cursor:pointer;list-style:none;padding:2px 5px}.yui3-aclist-item-active{outline:#afafaf dotted thin}.yui3-skin-sam .yui3-aclist-content{background:#fff;border:1px solid #afafaf;-moz-box-shadow:1px 1px 4px rgba(0,0,0,0.58);-webkit-box-shadow:1px 1px 4px rgba(0,0,0,0.58);box-shadow:1px 1px 4px rgba(0,0,0,0.58)}.yui3-skin-sam .yui3-aclist-item-hover{background:#bfdaff}.yui3-skin-sam .yui3-aclist-item-active{background:#2647a0;color:#fff;outline:0}#yui3-css-stamp.skin-sam-autocomplete-list{display:none}
+.yui3-calendar-pane{width:100%}.yui3-calendar-grid{width:100%}.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-skin-sam .yui3-calendar-content{padding:10px;color:#000;border:1px solid gray;background:#f2f2f2;background:-moz-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f9f9f9),color-stop(100%,#f2f2f2));background:-webkit-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-o-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-ms-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9',endColorstr='#f2f2f2',GradientType=0);background:linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);-moz-border-radius:5px;border-radius:5px}.yui3-skin-sam .yui3-calendar-grid{padding:5px;border-collapse:collapse}.yui3-skin-sam .yui3-calendar-header{padding-bottom:10px}.yui3-skin-sam .yui3-calendar-header-label{margin:0;font-size:1em;font-weight:bold}.yui3-skin-sam .yui3-calendar-day,.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{padding:5px;border:1px solid #ccc;background:#fff;text-align:center}.yui3-skin-sam .yui3-calendar-day:hover{background:#06c;color:#fff}.yui3-skin-sam .yui3-calendar-selection-disabled,.yui3-skin-sam .yui3-calendar-selection-disabled:hover{color:#a6a6a6;background:#ccc}.yui3-skin-sam .yui3-calendar-weekday{font-weight:bold}.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{color:#a6a6a6}.yui3-skin-sam .yui3-calendar-day{font-weight:bold}.yui3-skin-sam .yui3-calendar-day-selected{background-color:#b3d4ff;color:#000}.yui3-skin-sam .yui3-calendar-header-label{text-align:center}.yui3-skin-sam .yui3-calendar-left-grid{margin-right:1em}.yui3-skin-sam .yui3-calendar-right-grid{margin-left:1em}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar-base{display:none}
+.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-calendar-day{cursor:pointer}.yui3-calendar-selection-disabled{cursor:default}.yui3-calendar-prevmonth-day{cursor:default}.yui3-calendar-nextmonth-day{cursor:default}.yui3-calendar-content:hover .yui3-calendar-day,.yui3-calendar-content:hover .yui3-calendar-prevmonth-day,.yui3-calendar-content:hover .yui3-calendar-nextmonth-day{-moz-user-select:none}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar{display:none}
+.yui3-calendar-header{padding-left:15px;padding-right:15px}.yui3-calendar-header-label{width:100%}.yui3-calendarnav-prevmonth{cursor:pointer}.yui3-calendarnav-nextmonth{cursor:pointer}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth{color:#000;width:12px;height:14px;background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKNJREFUeNpiYCAeSAPxUiiWZqAi4ATiaiD+DMT/ofgzVIyTUsMDgfghksHo+CFUDcnAAIgP4DEYHR+A6iEIhIB4GgkGo+NpUDMwADMQFwHxBwoMh+EPULOYYYZ7APFVKhiMjkFmejBBLWFjoD5gQ+dQO4iwOloUiOdQYPgcqBkDl0zRQRQRGS2KGkVFHRB/QzL4G1SMk5qpQg6psJMjVhNAgAEAH+qPqeiPEUsAAAAASUVORK5CYII=);background-repeat:no-repeat}.yui3-skin-sam .yui3-calendarnav-prevmonth:hover,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPpJREFUeNpi/P//PwMxQD9jszSQ6oJyyy7O8H1KjD5GQhYADeYEUkVAXAHEPFDhL0DcAcR9QIu+k20B0PBAIDUBiOVwKHkExAVAS9aTZAHQYAOowfYMxIGDUIsu4LUAaLAQkGoB4kwG8sB0IK4BWvQOxQKgwcxAdj4Q1wExPwNl4CMQNwHxRKBFfxn10jd5ADm9QKzFQF1wDYiLmaAcNgbqA7CZTEBv7ADS2iDboN5joEIQgczSBpmNHsmiQKodiJPJNHwuEFcCDX49MMkUi0VRUB/hy2ggFy+jtKgohRYVnFDh79CiopuiogLNIjmobxigrn5EjD6AAAMAok9vhfHG8wQAAAAASUVORK5CYII=);color:#06c}.yui3-skin-sam .yui3-calendarnav-month-disabled,.yui3-skin-sam .yui3-calendarnav-month-disabled:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQhJREFUeNqs0yGLAlEUhuHrKoIgCFbBJghb3F+g0WrVarEqLIhBEEFYWKNNMBktU4z6C5RNkwyCyWQSTPuOfCOCrHNnxwMPyOGe73DAiTmOYywrhy/9/sTBZujN4k0KPbioi6teKuqCmsKGSN/10+q5ehN6QQkrLJB/Mp/Xm5VmAhdkMcEGZWNfZc1MlPGwII42dmiZ/1dLGW1lXhdU8YNvZEz0yijLy6z6FyTN6yvpX7DEOzo4vSD4pCwvc+lfcMEYBUwjhE+VMVbmw7/oiCY+sA4RvNZMUxmB38EWFTSwfxK815uKZkJ/yXMU0cf5rn9Wr6g3f1bC4nwvbIAZRup1Ay671a8AAwC3OzOqxK+rkwAAAABJRU5ErkJggg==);cursor:default;color:#ccc}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-prevmonth:hover{background-position:0 0;margin-left:-12px}.yui3-skin-sam .yui3-calendarnav-nextmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background-position:-12px 0;margin-right:-12px}.yui3-skin-sam .yui3-calendarnav-prevmonth span,.yui3-skin-sam .yui3-calendarnav-nextmonth span{display:none;*display:block}#yui3-css-stamp.skin-sam-calendarnavigator{display:none}
+.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{text-align:left;padding:5px 0;border:1px inset;margin:0 2px}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories{background:#fff;border-bottom:2px ridge}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{background:#fff;margin-bottom:2px;border-top:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-filter-label{white-space:nowrap;margin-left:1ex}#yui3-css-stamp.skin-sam-console-filters{display:none}
+.yui3-skin-sam .yui3-console-separate{position:absolute;right:1em;top:1em;z-index:999}.yui3-skin-sam .yui3-console-inline{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:top}.yui3-skin-sam .yui3-console-inline .yui3-console-content{position:relative}.yui3-skin-sam .yui3-console-content{background:#777;_background:#d8d8da url(bg.png) repeat-x 0 0;font:normal 13px/1.3 Arial,sans-serif;text-align:left;border:1px solid #777;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-bd,.yui3-skin-sam .yui3-console-ft{position:relative}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-ft .yui3-console-controls{text-align:right}.yui3-skin-sam .yui3-console-hd{background:#d8d8da url(bg.png) repeat-x 0 0;padding:1ex;border:1px solid transparent;_border:0 none;border-top-right-radius:10px;border-top-left-radius:10px;-moz-border-radius-topright:10px;-moz-border-radius-topleft:10px;-webkit-border-top-right-radius:10px;-webkit-border-top-left-radius:10px}.yui3-skin-sam .yui3-console-bd{background:#fff;border-top:1px solid #777;border-bottom:1px solid #777;color:#000;font-size:11px;overflow:auto;overflow-x:auto;overflow-y:scroll;_width:100%}.yui3-skin-sam .yui3-console-ft{background:#d8d8da url(bg.png) repeat-x 0 0;border:1px solid transparent;_border:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-controls{padding:4px 1ex;zoom:1}.yui3-skin-sam .yui3-console-title{color:#000;display:inline;float:left;font-weight:bold;font-size:13px;height:24px;line-height:24px;margin:0;padding-left:1ex}.yui3-skin-sam .yui3-console-pause-label{float:left}.yui3-skin-sam .yui3-console-button{line-height:1.3}.yui3-skin-sam .yui3-console-collapsed .yui3-console-bd,.yui3-skin-sam .yui3-console-collapsed .yui3-console-ft{display:none}.yui3-skin-sam .yui3-console-content.yui3-console-collapsed{-webkit-border-radius:0}.yui3-skin-sam .yui3-console-collapsed .yui3-console-hd{border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:0}.yui3-skin-sam .yui3-console-entry{border-bottom:1px solid #aaa;min-height:32px;_height:32px}.yui3-skin-sam .yui3-console-entry-meta{margin:0;overflow:hidden}.yui3-skin-sam .yui3-console-entry-content{margin:0;padding:0 1ex;white-space:pre-wrap;word-wrap:break-word}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-src{color:#000;font-style:italic;font-weight:bold;float:right;margin:2px 5px 0 0}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-time{color:#777;padding-left:1ex}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-time{color:#555}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-meta .yui3-console-entry-cat{display:none}.yui3-skin-sam .yui3-console-entry-warn{background:#aee url(warn_error.png) no-repeat -15px 15px}.yui3-skin-sam .yui3-console-entry-error{background:#ffa url(warn_error.png) no-repeat 5px -24px;color:#900}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-content,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-content{padding-left:24px}.yui3-skin-sam .yui3-console-entry-cat{text-transform:uppercase;padding:1px 4px;background-color:#ccc}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-cat{background-color:#ac2}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-cat{background-color:#e81}.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-cat{background-color:#b00;color:#fff}.yui3-skin-sam .yui3-console-hidden{display:none}#yui3-css-stamp.skin-sam-console{display:none}
+.yui3-skin-sam .yui3-datatable-mask{position:absolute;z-index:9500}.yui3-datatable-tmp{position:absolute;left:-9000px}.yui3-datatable-scrollable .yui3-datatable-bd{overflow:auto}.yui3-datatable-scrollable .yui3-datatable-hd{overflow:hidden;position:relative}.yui3-datatable-scrollable .yui3-datatable-bd thead tr,.yui3-datatable-scrollable .yui3-datatable-bd thead th{position:absolute;left:-1500px}.yui3-datatable-scrollable tbody{-moz-outline:0}.yui3-skin-sam thead .yui3-datatable-sortable{cursor:pointer}.yui3-skin-sam thead .yui3-datatable-draggable{cursor:move}.yui3-datatable-coltarget{position:absolute;z-index:999}.yui3-datatable-hd{zoom:1}th.yui3-datatable-resizeable .yui3-datatable-resizerliner{position:relative}.yui3-datatable-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui3-datatable-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui3-datatable-hidden .yui3-datatable-liner,td.yui3-datatable-hidden .yui3-datatable-liner,th.yui3-datatable-hidden .yui3-datatable-resizer{display:none}.yui3-datatable-editor,.yui3-datatable-editor-shim{position:absolute;z-index:9000}.yui3-skin-sam .yui3-datatable table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable thead{border-spacing:0}.yui3-skin-sam .yui3-datatable caption{color:#000;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable th{background:#d8d8da url(sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-datatable th,.yui3-skin-sam .yui3-datatable th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom}.yui3-skin-sam .yui3-datatable th{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable tr.yui3-datatable-first td{border-top:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable th .yui3-datatable-liner{white-space:nowrap}.yui3-skin-sam .yui3-datatable-liner{margin:0;padding:0;padding:4px 10px 4px 10px;overflow:visible;border:0 solid black}.yui3-skin-sam .yui3-datatable-coltarget{width:5px;background-color:red}.yui3-skin-sam .yui3-datatable td{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb;text-align:left}.yui3-skin-sam .yui3-datatable-list td{border-right:0}.yui3-skin-sam .yui3-datatable-resizer{width:6px}.yui3-skin-sam .yui3-datatable-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui3-skin-sam .yui3-datatable-message{background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable table{border:0}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-hd{border-left:1px solid #7f7f7f;border-top:1px solid #7f7f7f;border-right:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-bd{border-left:1px solid #7f7f7f;border-bottom:1px solid #7f7f7f;border-right:1px solid #7f7f7f;background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-data tr.yui3-datatable-last td{border-bottom:1px solid #7f7f7f}.yui3-skin-sam th.yui3-datatable-asc,.yui3-skin-sam th.yui3-datatable-desc{background:url(sprite.png) repeat-x 0 -100px}.yui3-skin-sam th.yui3-datatable-sortable .yui3-datatable-liner{padding-right:20px}.yui3-skin-sam th.yui3-datatable-asc .yui3-datatable-liner{background:url(dt-arrow-up.png) no-repeat right}.yui3-skin-sam th.yui3-datatable-desc .yui3-datatable-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui3-datatable-editable{cursor:pointer}.yui3-datatable-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui3-datatable-editor label{padding-left:4px;padding-right:6px}.yui3-datatable-editor .yui3-datatable-button{padding-top:6px;text-align:right}.yui3-datatable-editor .yui3-datatable-button button{background:url(sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui3-datatable-editor .yui3-datatable-button button.yui3-datatable-default{background:url(sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui3-datatable-editor .yui3-datatable-button button:hover{background:url(sprite.png) repeat-x 0 -1300px;color:#000}.yui3-datatable-editor .yui3-datatable-button button:active{background:url(sprite.png) repeat-x 0 -1700px;color:#000}.yui3-skin-sam .yui3-datatable td{background-color:transparent}.yui3-skin-sam tr.yui3-datatable-even td{background-color:#FFF}.yui3-skin-sam tr.yui3-datatable-odd td{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#dbeaff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam th.yui3-datatable-highlighted,.yui3-skin-sam th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam tr.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}
+.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}.yui3-skin-sam th.yui3-datatable-selected,.yui3-skin-sam th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam tr.yui3-datatable-selected td,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-paginator{display:block;margin:6px 0;white-space:nowrap}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-last,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-selected{padding:2px 6px}.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-last{text-decoration:none}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-previous,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-next{display:none}.yui3-skin-sam a.yui3-datatable-page{border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none;background-color:#fff}.yui3-skin-sam .yui3-datatable-selected{border:1px solid #fff;background-color:#fff}#yui3-css-stamp.skin-sam-datatable-base-deprecated{display:none}
+.yui3-datatable-table{empty-cells:show}.yui3-skin-sam .yui3-datatable-table{margin:0;padding:0;font-family:arial,sans-serif;border-collapse:separate;border-spacing:0;border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable-cell,.yui3-skin-sam .yui3-datatable-header{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:4px 10px 4px 10px}.yui3-skin-sam .yui3-datatable-cell:first-child,.yui3-skin-sam .yui3-datatable-first-header{border-left-width:0}.yui3-skin-sam .yui3-datatable-header{background:#fff url(sprite.png) repeat-x 0 0;background-image:-webkit-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-moz-linear-gradient(top,transparent 40%,rgba(0,0,0,0.21));background-image:-ms-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-o-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:linear-gradient(transparent 40%,rgba(0,0,0,0.21));color:#000;font-weight:normal;text-align:left;text-shadow:0 1px 1px #fff;vertical-align:bottom;white-space:nowrap}.yui3-skin-sam .yui3-datatable-cell{background-color:transparent}.yui3-skin-sam .yui3-datatable-even .yui3-datatable-cell{background-color:#fff}.yui3-skin-sam .yui3-datatable-odd .yui3-datatable-cell{background-color:#edf5ff}#yui3-css-stamp.skin-sam-datatable-base{display:none}
+.yui3-datatable-message{display:none}.yui3-datatable-message-visible .yui3-datatable-message{display:block;display:table-row-group}.yui3-skin-sam .yui3-datatable-message-content{border:0 none;border-bottom:1px solid #cbcbcb;padding:4px 10px}#yui3-css-stamp.skin-sam-datatable-message{display:none}
+.yui3-datatable-scrollable-x{_overflow-x:hidden;_position:relative}.yui3-datatable-scrollable-y,.yui3-datatable-scrollable-y .yui3-datatable-x-scroller{_overflow-y:hidden;_position:relative}.yui3-datatable-y-scroller-container{overflow-x:hidden;position:relative}.yui3-datatable-scrollable-y .yui3-datatable-content{position:relative}.yui3-datatable-scrollable-y .yui3-datatable-table .yui3-datatable-columns{visibility:hidden}.yui3-datatable-scroll-columns{position:absolute;width:100%;z-index:2}.yui3-datatable-y-scroller,.yui3-datatable-scrollable-x .yui3-datatable-caption-table{width:100%}.yui3-datatable-x-scroller{position:relative;overflow-x:scroll;overflow-y:hidden}.yui3-datatable-scrollable-y .yui3-datatable-y-scroller{position:relative;overflow-x:hidden;overflow-y:scroll;z-index:1;-webkit-overflow-scrolling:touch}.yui3-datatable-scrollbar{position:absolute;overflow-x:hidden;overflow-y:scroll;z-index:2}.yui3-datatable-scrollbar div{position:absolute;width:1px;visibility:hidden}.yui3-skin-sam .yui3-datatable-scroll-columns{border-collapse:separate;border-spacing:0;font-family:arial,sans-serif;margin:0;padding:0;top:0;left:0}.yui3-skin-sam .yui3-datatable-scroll-columns .yui3-datatable-header{padding:0}.yui3-skin-sam .yui3-datatable-x-scroller,.yui3-skin-sam .yui3-datatable-y-scroller-container{border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-scrollable-x .yui3-datatable-y-scroller-container,.yui3-skin-sam .yui3-datatable-x-scroller .yui3-datatable-table,.yui3-skin-sam .yui3-datatable-y-scroller .yui3-datatable-table{border:0 none}#yui3-css-stamp.skin-sam-datatable-scroll{display:none}
+.yui3-datatable-sortable-column{z-index:1}.yui3-datatable-sortable-column:focus,.yui3-datatable-sortable-column:active{z-index:2}.yui3-skin-sam .yui3-datatable-sortable-column{cursor:pointer}.yui3-skin-sam .yui3-datatable-columns .yui3-datatable-sorted,.yui3-skin-sam .yui3-datatable-sortable-column:hover{*background:#c1c4c8 url(sprite.png) repeat-x 0 -100px;background-color:#f1f2f3}.yui3-skin-sam .yui3-datatable-sort-liner{display:block;height:100%;position:relative;padding-right:15px;position:relative}.yui3-skin-sam .yui3-datatable-sort-indicator{position:absolute;right:0;bottom:.5ex;width:7px;height:10px;background:url(sort-arrow-sprite.png) no-repeat 0 0;_background:url(sort-arrow-sprite-ie.png) no-repeat 0 0;overflow:hidden}.yui3-skin-sam .yui3-datatable-sorted .yui3-datatable-sort-indicator{background-position:0 -10px}.yui3-skin-sam .yui3-datatable-sorted-desc .yui3-datatable-sort-indicator{background-position:0 -20px}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted{background-color:#dbeaff}#yui3-css-stamp.skin-sam-datatable-sort{display:none}
+v\:oval,v\:shadow,v\:fill{behavior:url(#default#VML);display:inline-block;zoom:1;*display:inline}.yui3-dial{position:relative;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.yui3-dial-content,.yui3-dial-ring{position:relative}.yui3-dial-handle,.yui3-dial-marker,.yui3-dial-center-button,.yui3-dial-reset-string,.yui3-dial-handle-vml,.yui3-dial-marker-vml,.yui3-dial-center-button-vml,.yui3-dial-ring-vml v\:oval,.yui3-dial-center-button-vml v\:oval{position:absolute}.yui3-dial-center-button-vml v\:oval{font-size:1px;top:0;left:0}.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden v\:oval,.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden{opacity:0;filter:alpha(opacity=0)}.yui3-skin-sam .yui3-dial-handle{background:#6c3a3a;opacity:.3;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;cursor:pointer;font-size:1px}.yui3-skin-sam .yui3-dial-ring{background:#bebdb7;background:-moz-linear-gradient(100% 100% 135deg,#7b7a6d,#fff);background:-webkit-gradient(linear,left top,right bottom,from(#fff),to(#7b7a6d));box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-webkit-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-moz-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset}.yui3-skin-sam .yui3-dial-center-button{box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);-moz-box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);background:#dddbd4;background:-moz-radial-gradient(30% 30% 0deg,circle farthest-side,#fbfbf9 24%,#f2f0ea 41%,#d3d0c3 83%) repeat scroll 0 0 transparent;background:-webkit-gradient(radial,15 15,15,30 30,40,from(#fbfbf9),to(#d3d0c3),color-stop(.2,#f2f0ea));cursor:pointer;opacity:.7}.yui3-skin-sam .yui3-dial-reset-string{color:#676767;font-size:85%;text-decoration:underline}.yui3-skin-sam .yui3-dial-label{color:#808080;margin-bottom:.8em}.yui3-skin-sam .yui3-dial-value-string{margin-left:.5em;color:#000;font-size:130%}.yui3-skin-sam .yui3-dial-value{visibility:hidden;position:absolute;top:0;left:102%;width:4em}.yui3-skin-sam .yui3-dial-north-mark{position:absolute;border-left:2px solid #ccc;height:5px;width:10px;left:50%;top:-7px;font-size:1px}.yui3-skin-sam .yui3-dial-marker{background-color:#000;opacity:.2;font-size:1px}.yui3-skin-sam .yui3-dial-marker-max-min{background-color:#ab3232;opacity:.6}.yui3-skin-sam .yui3-dial-ring-vml,.yui3-skin-sam .yui3-dial-center-button-vml,.yui3-skin-sam .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam .yui3-dial-marker-vml,.yui3-skin-sam .yui3-dial-handle-vml{background:0;opacity:1}#yui3-css-stamp.skin-sam-dial{display:none}
+.yui3-flick{position:relative;overflow:hidden}.yui3-flick-content{position:relative}#yui3-css-stamp.skin-sam-node-flick{display:none}
+.yui3-menu .yui3-menu{position:absolute;z-index:1}.yui3-menu .yui3-shim{position:absolute;top:0;left:0;z-index:-1;opacity:0;filter:alpha(opacity=0);border:0;margin:0;padding:0;height:100%;width:100%}.yui3-menu-hidden{top:-10000px;left:-10000px;visibility:hidden}.yui3-menu li{list-style-type:none}.yui3-menu ul,.yui3-menu li{margin:0;padding:0}.yui3-menu-label,.yui3-menuitem-content{text-align:left;white-space:nowrap;display:block}.yui3-menu-horizontal li{float:left;width:auto}.yui3-menu-horizontal li li{float:none}.yui3-menu-horizontal ul{*zoom:1}.yui3-menu-horizontal ul ul{*zoom:normal}.yui3-menu-horizontal>.yui3-menu-content>ul:after{content:"";display:block;clear:both;line-height:0;font-size:0;visibility:hidden}.yui3-menu-content{*zoom:1}.yui3-menu-hidden .yui3-menu-content{*zoom:normal}.yui3-menuitem-content,.yui3-menu-label{_zoom:1}.yui3-menu-hidden .yui3-menuitem-content,.yui3-menu-hidden .yui3-menu-label{_zoom:normal}.yui3-skin-sam .yui3-menu-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:93%;line-height:1.5;*line-height:1.45;border:solid 1px #808080;background:#fff;padding:3px 0}.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:100%}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-content{line-height:2;*line-height:1.9;background:url(sprite.png) repeat-x 0 0;padding:0}.yui3-skin-sam .yui3-menu ul,.yui3-skin-sam .yui3-menu ul ul{margin-top:3px;padding-top:3px;border-top:solid 1px #ccc}.yui3-skin-sam .yui3-menu ul.first-of-type{border:0;margin:0;padding:0}.yui3-skin-sam .yui3-menu-horizontal ul{padding:0;margin:0;border:0}.yui3-skin-sam .yui3-menu li,.yui3-skin-sam .yui3-menu .yui3-menu li{_border-bottom:solid 1px #fff}.yui3-skin-sam .yui3-menu-horizontal li{_border-bottom:0}.yui3-skin-sam .yui3-menubuttonnav li{border-right:solid 1px #ccc}.yui3-skin-sam .yui3-splitbuttonnav li{border-right:solid 1px #808080}.yui3-skin-sam .yui3-menubuttonnav li li,.yui3-skin-sam .yui3-splitbuttonnav li li{border-right:0}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label,.yui3-skin-sam .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-content{padding:0 1em;color:#000;text-decoration:none;cursor:default;float:none;border:0;margin:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-content{padding:0 10px;border-style:solid;border-color:#808080;border-width:1px 0;margin:-1px 0;float:left;width:auto}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label{background:url(vertical-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label{background:url(sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{background-image:none}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label{padding-right:0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label em{font-style:normal;padding-right:20px;display:block;background:url(horizontal-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{padding:0}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label a{float:left;width:auto;color:#000;text-decoration:none;cursor:default;padding:0 5px 0 10px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label .yui3-menu-toggle{padding:0;border-left:solid 1px #ccc;width:15px;overflow:hidden;text-indent:-1000px;background:url(horizontal-menu-submenu-indicator.png) 3px center no-repeat}.yui3-skin-sam .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-active,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-menuvisible{background-color:#b3d4ff}.yui3-skin-sam .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content{background-image:none;background-color:#b3d4ff;border-left-width:0;margin-left:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-menuvisible{border-color:#7d98b8;background:url(sprite.png) repeat-x 0 -1700px}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-menubuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-left-width:1px;margin-left:-1px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-color:#808080;background:transparent}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible .yui3-menu-toggle{border-color:#7d98b8;background:url(horizontal-menu-submenu-toggle.png) left center no-repeat}#yui3-css-stamp.skin-sam-node-menunav{display:none}
+.yui3-overlay{position:absolute}.yui3-overlay-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-overlay-content{overflow:hidden!important}#yui3-css-stamp.skin-sam-overlay{display:none}
+.yui3-panel{position:absolute}.yui3-panel-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-panel-content{overflow:hidden!important}.yui3-panel .yui3-widget-hd{position:relative}.yui3-panel .yui3-widget-hd .yui3-widget-buttons{position:absolute;top:0;right:0}.yui3-panel .yui3-widget-ft .yui3-widget-buttons{display:inline-block;*display:inline;zoom:1}.yui3-skin-sam .yui3-panel-content{-webkit-box-shadow:0 0 5px #333;-moz-box-shadow:0 0 5px #333;box-shadow:0 0 5px #333;border:1px solid black;background:white}.yui3-skin-sam .yui3-panel .yui3-widget-hd{padding:8px 28px 8px 8px;min-height:13px;_height:13px;color:white;background-color:#3961c5;background:-moz-linear-gradient(0% 100% 90deg,#2647a0 7%,#3d67ce 50%,#426fd9 100%);background:-webkit-gradient(linear,left bottom,left top,from(#2647a0),color-stop(0.07,#2647a0),color-stop(0.5,#3d67ce),to(#426fd9))}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-widget-buttons{padding:8px}.yui3-skin-sam .yui3-panel .yui3-widget-bd{padding:10px}.yui3-skin-sam .yui3-panel .yui3-widget-ft{background:#edf5ff;padding:8px;text-align:right}.yui3-skin-sam .yui3-panel .yui3-widget-ft .yui3-button{margin-left:8px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close{background:transparent;filter:none;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;width:13px;height:13px;padding:0;overflow:hidden;vertical-align:top;*font-size:0;*line-height:0;*letter-spacing:-1000px;*color:#86a5ec;*background:url(sprite_icons.png) no-repeat 1px 1px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close:before{content:url(sprite_icons.png);display:inline-block;text-align:center;font-size:0;line-height:0;width:13px;margin:1px 0 0 1px}.yui3-skin-sam .yui3-panel-hidden .yui3-widget-hd .yui3-button-close{display:none}#yui3-css-stamp.skin-sam-panel{display:none}
+.yui3-resize,.yui3-resize-wrapper{z-index:0;zoom:1}.yui3-resize-handle{position:absolute;display:block;z-index:100;zoom:1}.yui3-resize-proxy{position:absolute;border:1px dashed #000;position:absolute;z-index:10000}.yui3-resize-hidden-handles .yui3-resize-handle{opacity:0;filter:alpha(opacity=0)}.yui3-resize-handle-t,.yui3-resize-handle-b{width:100%;left:0;height:6px}.yui3-resize-handle-l,.yui3-resize-handle-r{height:100%;top:0;width:6px}.yui3-resize-handle-t{cursor:n-resize;top:0}.yui3-resize-handle-b{cursor:s-resize;bottom:0}.yui3-resize-handle-l{cursor:w-resize;left:0}.yui3-resize-handle-r{cursor:e-resize;right:0}.yui3-resize-handle-inner{position:absolute;zoom:1}@media only screen and (min-device-width :320px) and (max-device-width:480px){.yui3-resize-handle-inner:after{content:"";width:40px;height:40px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-12px;right:0}.yui3-resize-handle-inner-l:after{top:-12px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-12px}.yui3-resize-handle-inner-b:after{bottom:0;left:-12px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}@media only screen and (min-device-width :768px) and (max-device-width:1024px){.yui3-resize-handle-inner:after{content:"";width:30px;height:30px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-6px;right:0}.yui3-resize-handle-inner-l:after{top:-6px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-6px}.yui3-resize-handle-inner-b:after{bottom:0;left:-6px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b{margin-left:-8px;left:50%}.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-r{margin-top:-8px;top:50%}.yui3-resize-handle-inner-t{top:-4px}.yui3-resize-handle-inner-b{bottom:-4px}.yui3-resize-handle-inner-l{left:-4px}.yui3-resize-handle-inner-r{right:-4px}.yui3-resize-handle-tr,.yui3-resize-handle-br,.yui3-resize-handle-tl,.yui3-resize-handle-bl{height:15px;width:15px;z-index:200}.yui3-resize-handle-tr{cursor:ne-resize;top:0;right:0}.yui3-resize-handle-tl{cursor:nw-resize;top:0;left:0}.yui3-resize-handle-br{cursor:se-resize;bottom:0;right:0}.yui3-resize-handle-bl{cursor:sw-resize;bottom:0;left:0}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{background-repeat:no-repeat;background:url(arrows.png) no-repeat 0 0;display:block;height:15px;overflow:hidden;text-indent:-99999em;width:15px}.yui3-resize-handle-inner-br{background-position:-30px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tr{background-position:-58px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-bl{background-position:-75px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tl{background-position:-47px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t{background-position:-15px 0}#yui3-css-stamp.skin-sam-resize-base{display:none}
+.yui3-scrollview{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none}.yui3-scrollview-hidden{display:none}.yui3-scrollview-content{position:relative}.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}#yui3-css-stamp.skin-sam-scrollview-base{display:none}
+.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}.yui3-skin-sam .yui3-scrollview{background-color:white}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{*zoom:1}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-list{*zoom:1;list-style:none;padding:0;margin:0}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content{border-top:0;background-color:white;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:black}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{border-bottom:1px solid #303030;padding:15px 20px 16px;font-size:100%;font-weight:bold;background-color:white;cursor:pointer}#yui3-css-stamp.skin-sam-scrollview-list{display:none}
+.yui3-scrollview-scrollbar{opacity:1;position:absolute;width:6px;height:10px}.yui3-scrollview-scrollbar{top:0;right:1px}.yui3-scrollview-scrollbar-horiz{top:auto;height:8px;width:20px;bottom:1px;left:0}.yui3-scrollview-scrollbar .yui3-scrollview-child{position:absolute;right:0;display:block;width:100%;height:4px}.yui3-scrollview-scrollbar .yui3-scrollview-first{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-last{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-middle{position:absolute;top:4px;height:1px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-child{display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline;top:0;left:0;bottom:auto;right:auto}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{width:4px;height:6px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{top:0;left:4px;width:1px;height:6px}.yui3-scrollview-scrollbar-vert-basic{height:auto}.yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child{position:static;_overflow:hidden;_line-height:4px}.yui3-scrollview-scrollbar-horiz-basic{width:auto;white-space:nowrap;line-height:6px;_overflow:hidden}.yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{position:static;padding:0;margin:0;top:auto;left:auto;right:auto;bottom:auto}.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none}#yui3-css-stamp.skin-sam-scrollview-scrollbars{display:none}
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail{height:26px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb{height:26px;width:15px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail{width:26px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb{width:26px;height:15px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-sam-slider-base{display:none}
+.yui3-tab-panel{display:none}.yui3-tab-panel-selected{display:block}.yui3-tabview-list,.yui3-tab{margin:0;padding:0;list-style:none}.yui3-tabview{position:relative}.yui3-tabview,.yui3-tabview-list,.yui3-tabview-panel,.yui3-tab,.yui3-tab-panel{zoom:1}.yui3-tab{display:inline-block;*display:inline;vertical-align:bottom;cursor:pointer}.yui3-tab-label{display:block;display:inline-block;padding:6px 10px;position:relative;text-decoration:none;vertical-align:bottom}.yui3-skin-sam .yui3-tabview-list{border:solid #2647a0;border-width:0 0 5px;zoom:1}.yui3-skin-sam .yui3-tab{margin:0 .2em 0 0;padding:1px 0 0;zoom:1}.yui3-skin-sam .yui3-tab-selected{margin-bottom:-1px}.yui3-skin-sam .yui3-tab-label{background:#d8d8d8 url(sprite.png) repeat-x;border:solid #a3a3a3;border-width:1px 1px 0 1px;color:#000;cursor:pointer;font-size:85%;padding:.3em .75em;text-decoration:none}.yui3-skin-sam .yui3-tab-label:hover,.yui3-skin-sam .yui3-tab-label:focus{background:#bfdaff url(sprite.png) repeat-x left -1300px;outline:0}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:focus,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:hover{background:#2647a0 url(sprite.png) repeat-x left -1400px;color:#fff}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{padding:.4em .75em}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{border-color:#243356}.yui3-skin-sam .yui3-tabview-panel{background:#edf5ff}.yui3-skin-sam .yui3-tabview-panel{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em}#yui3-css-stamp.skin-sam-tabview{display:none}
+.yui3-testconsole .yui3-console-entry{min-height:inherit;padding:5px}.yui3-testconsole .yui3-console-controls{display:none}.yui3-skin-sam .yui3-testconsole .yui3-console-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd,.yui3-skin-sam .yui3-testconsole .yui3-console-entry,.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-sources,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{background:0;border:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.yui3-skin-sam .yui3-testconsole-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd{color:#333;font:13px/1.4 Helvetica,'DejaVu Sans','Bitstream Vera Sans',Arial,sans-serif}.yui3-skin-sam .yui3-testconsole-content{border:1px solid #afafaf}.yui3-skin-sam .yui3-testconsole .yui3-console-entry{border-bottom:1px solid #eaeaea;font-family:Menlo,Inconsolata,Consolas,'DejaVu Mono','Bitstream Vera Sans Mono',monospace;font-size:11px}.yui3-skin-sam .yui3-testconsole .yui3-console-ft{border-top:1px solid}.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-bottom:1px solid;*zoom:1}.yui3-skin-sam .yui3-testconsole.yui3-console-collapsed .yui3-console-hd{border:0}.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-color:#cfcfcf}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-fail{background-color:#ffe0e0;border-bottom-color:#ffc5c4}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-pass{background-color:#ecffea;border-bottom-color:#d1ffcc}#yui3-css-stamp.skin-sam-test-console{display:none}
+.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}#yui3-css-stamp.skin-sam-widget-base{display:none}
+.yui3-widget-buttons .yui3-button-close,.yui3-widget-buttons .yui3-button-close .yui3-button-content,.yui3-widget-buttons .yui3-button-close .yui3-button-icon{display:inline-block;*display:inline;zoom:1;width:13px;height:13px;line-height:13px;vertical-align:top}.yui3-widget-buttons .yui3-button-close .yui3-button-icon{background-repeat:no-repeat;background-position:1px 1px}.yui3-skin-sam .yui3-widget-buttons .yui3-button-icon{background-image:url(sprite_icons.gif)}#yui3-css-stamp.skin-sam-widget-buttons{display:none}
+.yui3-skin-sam .yui3-widget-mask{background-color:black;zoom:1;-ms-filter:"alpha(opacity=40)";filter:alpha(opacity=40);opacity:.4}#yui3-css-stamp.skin-sam-widget-modality{display:none}
+.yui3-widget-stacked .yui3-widget-shim{opacity:0;filter:alpha(opacity=0);position:absolute;border:0;top:0;left:0;padding:0;margin:0;z-index:-1;width:100%;height:100%;_width:0;_height:0}#yui3-css-stamp.skin-sam-widget-stack{display:none}
diff --git a/js/yui3/assets/skins/sam/slider-base.css b/js/yui3/assets/skins/sam/slider-base.css
new file mode 100644
index 000000000..0bca65481
--- /dev/null
+++ b/js/yui3/assets/skins/sam/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail{height:26px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb{height:26px;width:15px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail{width:26px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb{width:26px;height:15px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-sam-slider-base{display:none}
diff --git a/js/yui3/assets/skins/sam/sort-arrow-sprite-ie.png b/js/yui3/assets/skins/sam/sort-arrow-sprite-ie.png
new file mode 100644
index 000000000..f1f6576ab
--- /dev/null
+++ b/js/yui3/assets/skins/sam/sort-arrow-sprite-ie.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/sort-arrow-sprite.png b/js/yui3/assets/skins/sam/sort-arrow-sprite.png
new file mode 100644
index 000000000..47b8b1550
--- /dev/null
+++ b/js/yui3/assets/skins/sam/sort-arrow-sprite.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/sprite.png b/js/yui3/assets/skins/sam/sprite.png
new file mode 100644
index 000000000..321bc3f25
--- /dev/null
+++ b/js/yui3/assets/skins/sam/sprite.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/sprite_icons.gif b/js/yui3/assets/skins/sam/sprite_icons.gif
new file mode 100644
index 000000000..fa26094f6
--- /dev/null
+++ b/js/yui3/assets/skins/sam/sprite_icons.gif
Binary files differ
diff --git a/js/yui3/assets/skins/sam/sprite_icons.png b/js/yui3/assets/skins/sam/sprite_icons.png
new file mode 100644
index 000000000..89944ba0f
--- /dev/null
+++ b/js/yui3/assets/skins/sam/sprite_icons.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/tabview.css b/js/yui3/assets/skins/sam/tabview.css
new file mode 100644
index 000000000..258c6ea38
--- /dev/null
+++ b/js/yui3/assets/skins/sam/tabview.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel{display:none}.yui3-tab-panel-selected{display:block}.yui3-tabview-list,.yui3-tab{margin:0;padding:0;list-style:none}.yui3-tabview{position:relative}.yui3-tabview,.yui3-tabview-list,.yui3-tabview-panel,.yui3-tab,.yui3-tab-panel{zoom:1}.yui3-tab{display:inline-block;*display:inline;vertical-align:bottom;cursor:pointer}.yui3-tab-label{display:block;display:inline-block;padding:6px 10px;position:relative;text-decoration:none;vertical-align:bottom}.yui3-skin-sam .yui3-tabview-list{border:solid #2647a0;border-width:0 0 5px;zoom:1}.yui3-skin-sam .yui3-tab{margin:0 .2em 0 0;padding:1px 0 0;zoom:1}.yui3-skin-sam .yui3-tab-selected{margin-bottom:-1px}.yui3-skin-sam .yui3-tab-label{background:#d8d8d8 url(sprite.png) repeat-x;border:solid #a3a3a3;border-width:1px 1px 0 1px;color:#000;cursor:pointer;font-size:85%;padding:.3em .75em;text-decoration:none}.yui3-skin-sam .yui3-tab-label:hover,.yui3-skin-sam .yui3-tab-label:focus{background:#bfdaff url(sprite.png) repeat-x left -1300px;outline:0}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:focus,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:hover{background:#2647a0 url(sprite.png) repeat-x left -1400px;color:#fff}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{padding:.4em .75em}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{border-color:#243356}.yui3-skin-sam .yui3-tabview-panel{background:#edf5ff}.yui3-skin-sam .yui3-tabview-panel{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em}#yui3-css-stamp.skin-sam-tabview{display:none}
diff --git a/js/yui3/assets/skins/sam/test-console.css b/js/yui3/assets/skins/sam/test-console.css
new file mode 100644
index 000000000..9f1fb25dc
--- /dev/null
+++ b/js/yui3/assets/skins/sam/test-console.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-testconsole .yui3-console-entry{min-height:inherit;padding:5px}.yui3-testconsole .yui3-console-controls{display:none}.yui3-skin-sam .yui3-testconsole .yui3-console-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd,.yui3-skin-sam .yui3-testconsole .yui3-console-entry,.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-sources,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{background:0;border:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.yui3-skin-sam .yui3-testconsole-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd{color:#333;font:13px/1.4 Helvetica,'DejaVu Sans','Bitstream Vera Sans',Arial,sans-serif}.yui3-skin-sam .yui3-testconsole-content{border:1px solid #afafaf}.yui3-skin-sam .yui3-testconsole .yui3-console-entry{border-bottom:1px solid #eaeaea;font-family:Menlo,Inconsolata,Consolas,'DejaVu Mono','Bitstream Vera Sans Mono',monospace;font-size:11px}.yui3-skin-sam .yui3-testconsole .yui3-console-ft{border-top:1px solid}.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-bottom:1px solid;*zoom:1}.yui3-skin-sam .yui3-testconsole.yui3-console-collapsed .yui3-console-hd{border:0}.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-color:#cfcfcf}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-fail{background-color:#ffe0e0;border-bottom-color:#ffc5c4}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-pass{background-color:#ecffea;border-bottom-color:#d1ffcc}#yui3-css-stamp.skin-sam-test-console{display:none}
diff --git a/js/yui3/assets/skins/sam/thumb-x.png b/js/yui3/assets/skins/sam/thumb-x.png
new file mode 100644
index 000000000..4d4bcbd48
--- /dev/null
+++ b/js/yui3/assets/skins/sam/thumb-x.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/thumb-y.png b/js/yui3/assets/skins/sam/thumb-y.png
new file mode 100644
index 000000000..0b17a0ed2
--- /dev/null
+++ b/js/yui3/assets/skins/sam/thumb-y.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/vertical-menu-submenu-indicator.png b/js/yui3/assets/skins/sam/vertical-menu-submenu-indicator.png
new file mode 100644
index 000000000..cfc46b8ac
--- /dev/null
+++ b/js/yui3/assets/skins/sam/vertical-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/warn_error.png b/js/yui3/assets/skins/sam/warn_error.png
new file mode 100644
index 000000000..8b0db799e
--- /dev/null
+++ b/js/yui3/assets/skins/sam/warn_error.png
Binary files differ
diff --git a/js/yui3/assets/skins/sam/widget-base.css b/js/yui3/assets/skins/sam/widget-base.css
new file mode 100644
index 000000000..118a6ec1b
--- /dev/null
+++ b/js/yui3/assets/skins/sam/widget-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}#yui3-css-stamp.skin-sam-widget-base{display:none}
diff --git a/js/yui3/assets/skins/sam/widget-buttons.css b/js/yui3/assets/skins/sam/widget-buttons.css
new file mode 100644
index 000000000..bef96b104
--- /dev/null
+++ b/js/yui3/assets/skins/sam/widget-buttons.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-buttons .yui3-button-close,.yui3-widget-buttons .yui3-button-close .yui3-button-content,.yui3-widget-buttons .yui3-button-close .yui3-button-icon{display:inline-block;*display:inline;zoom:1;width:13px;height:13px;line-height:13px;vertical-align:top}.yui3-widget-buttons .yui3-button-close .yui3-button-icon{background-repeat:no-repeat;background-position:1px 1px}.yui3-skin-sam .yui3-widget-buttons .yui3-button-icon{background-image:url(sprite_icons.gif)}#yui3-css-stamp.skin-sam-widget-buttons{display:none}
diff --git a/js/yui3/assets/skins/sam/widget-modality.css b/js/yui3/assets/skins/sam/widget-modality.css
new file mode 100644
index 000000000..b3c0198df
--- /dev/null
+++ b/js/yui3/assets/skins/sam/widget-modality.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-widget-mask{background-color:black;zoom:1;-ms-filter:"alpha(opacity=40)";filter:alpha(opacity=40);opacity:.4}#yui3-css-stamp.skin-sam-widget-modality{display:none}
diff --git a/js/yui3/assets/skins/sam/widget-stack.css b/js/yui3/assets/skins/sam/widget-stack.css
new file mode 100644
index 000000000..61ac07ba4
--- /dev/null
+++ b/js/yui3/assets/skins/sam/widget-stack.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-stacked .yui3-widget-shim{opacity:0;filter:alpha(opacity=0);position:absolute;border:0;top:0;left:0;padding:0;margin:0;z-index:-1;width:100%;height:100%;_width:0;_height:0}#yui3-css-stamp.skin-sam-widget-stack{display:none}
diff --git a/js/yui3/async-queue/async-queue-min.js b/js/yui3/async-queue/async-queue-min.js
new file mode 100644
index 000000000..649e75b19
--- /dev/null
+++ b/js/yui3/async-queue/async-queue-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("async-queue",function(e,t){e.AsyncQueue=function(){this._init(),this.add.apply(this,arguments)};var n=e.AsyncQueue,r="execute",i="shift",s="promote",o="remove",u=e.Lang.isObject,a=e.Lang.isFunction;n.defaults=e.mix({autoContinue:!0,iterations:1,timeout:10,until:function(){return this.iterations|=0,this.iterations<=0}},e.config.queueDefaults||{}),e.extend(n,e.EventTarget,{_running:!1,_init:function(){e.EventTarget.call(this,{prefix:"queue",emitFacade:!0}),this._q=[],this.defaults={},this._initEvents()},_initEvents:function(){this.publish({execute:{defaultFn:this._defExecFn,emitFacade:!0},shift:{defaultFn:this._defShiftFn,emitFacade:!0},add:{defaultFn:this._defAddFn,emitFacade:!0},promote:{defaultFn:this._defPromoteFn,emitFacade:!0},remove:{defaultFn:this._defRemoveFn,emitFacade:!0}})},next:function(){var e;while(this._q.length){e=this._q[0]=this._prepare(this._q[0]);if(!e||!e.until())break;this.fire(i,{callback:e}),e=null}return e||null},_defShiftFn:function(e){this.indexOf(e.callback)===0&&this._q.shift()},_prepare:function(t){if(a(t)&&t._prepared)return t;var r=e.merge(n.defaults,{context:this,args:[],_prepared:!0},this.defaults,a(t)?{fn:t}:t),i=e.bind(function(){i._running||i.iterations--,a(i.fn)&&i.fn.apply(i.context||e,e.Array(i.args))},this);return e.mix(i,r)},run:function(){var e,t=!0;for(e=this.next();t&&e&&!this.isRunning();e=this.next())t=e.timeout<0?this._execute(e):this._schedule(e);return e||this.fire("complete"),this},_execute:function(e){this._running=e._running=!0,e.iterations--,this.fire(r,{callback:e});var t=this._running&&e.autoContinue;return this._running=e._running=!1,t},_schedule:function(t){return this._running=e.later(t.timeout,this,function(){this._execute(t)&&this.run()}),!1},isRunning:function(){return!!this._running},_defExecFn:function(e){e.callback()},add:function(){return this.fire("add",{callbacks:e.Array(arguments,0,!0)}),this},_defAddFn:function(t){var n=this._q,r=[];e.Array.each(t.callbacks,function(e){u(e)&&(n.push(e),r.push(e))}),t.added=r},pause:function(){return u(this._running)&&this._running.cancel(),this._running=!1,this},stop:function(){return this._q=[],this.pause()},indexOf:function(e){var t=0,n=this._q.length,r;for(;t<n;++t){r=this._q[t];if(r===e||r.id===e)return t}return-1},getCallback:function(e){var t=this.indexOf(e);return t>-1?this._q[t]:null},promote:function(e){var t={callback:e},n;return this.isRunning()?n=this.after(i,function(){this.fire(s,t),n.detach()},this):this.fire(s,t),this},_defPromoteFn:function(e){var t=this.indexOf(e.callback),n=t>-1?this._q.splice(t,1)[0]:null;e.promoted=n,n&&this._q.unshift(n)},remove:function(e){var t={callback:e},n;return this.isRunning()?n=this.after(i,function(){this.fire(o,t),n.detach()},this):this.fire(o,t),this},_defRemoveFn:function(e){var t=this.indexOf(e.callback);e.removed=t>-1?this._q.splice(t,1)[0]:null},size:function(){return this.isRunning()||this.next(),this._q.length}})},"3.7.3",{requires:["event-custom"]});
diff --git a/js/yui3/attribute-base/attribute-base-min.js b/js/yui3/attribute-base/attribute-base-min.js
new file mode 100644
index 000000000..f02c1755b
--- /dev/null
+++ b/js/yui3/attribute-base/attribute-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("attribute-base",function(e,t){var n=function(){this._ATTR_E_FACADE=null,this._yuievt=null,e.AttributeCore.apply(this,arguments),e.AttributeEvents.apply(this,arguments),e.AttributeExtras.apply(this,arguments)};e.mix(n,e.AttributeCore,!1,null,1),e.mix(n,e.AttributeExtras,!1,null,1),e.mix(n,e.AttributeEvents,!0,null,1),n.INVALID_VALUE=e.AttributeCore.INVALID_VALUE,n._ATTR_CFG=e.AttributeCore._ATTR_CFG.concat(e.AttributeEvents._ATTR_CFG),e.Attribute=n},"3.7.3",{requires:["attribute-core","attribute-events","attribute-extras"]});
diff --git a/js/yui3/attribute-complex/attribute-complex-min.js b/js/yui3/attribute-complex/attribute-complex-min.js
new file mode 100644
index 000000000..e8b036679
--- /dev/null
+++ b/js/yui3/attribute-complex/attribute-complex-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("attribute-complex",function(e,t){var n=e.Object,r=".";e.Attribute.Complex=function(){},e.Attribute.Complex.prototype={_normAttrVals:function(e){var t={},n={},i,s,o,u;if(e){for(u in e)e.hasOwnProperty(u)&&(u.indexOf(r)!==-1?(i=u.split(r),s=i.shift(),o=n[s]=n[s]||[],o[o.length]={path:i,value:e[u]}):t[u]=e[u]);return{simple:t,complex:n}}return null},_getAttrInitVal:function(e,t,r){var i=t.value,s=t.valueFn,o,u=!1,a,f,l,c,h,p,d;!t.readOnly&&r&&(a=r.simple,a&&a.hasOwnProperty(e)&&(i=a[e],u=!0)),s&&!u&&(s.call||(s=this[s]),s&&(o=s.call(this,e),i=o));if(!t.readOnly&&r){f=r.complex;if(f&&f.hasOwnProperty(e)&&i!==undefined&&i!==null){d=f[e];for(l=0,c=d.length;l<c;++l)h=d[l].path,p=d[l].value,n.setValue(i,h,p)}}return i}},e.mix(e.Attribute,e.Attribute.Complex,!0,null,1),e.AttributeComplex=e.Attribute.Complex},"3.7.3",{requires:["attribute-base"]});
diff --git a/js/yui3/attribute-core/attribute-core-min.js b/js/yui3/attribute-core/attribute-core-min.js
new file mode 100644
index 000000000..5525d3380
--- /dev/null
+++ b/js/yui3/attribute-core/attribute-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("attribute-core",function(e,t){function E(e,t,n){this._initAttrHost(e,t,n)}e.State=function(){this.data={}},e.State.prototype={add:function(e,t,n){var r=this.data[e];r||(r=this.data[e]={}),r[t]=n},addAll:function(e,t){var n=this.data[e],r;n||(n=this.data[e]={});for(r in t)t.hasOwnProperty(r)&&(n[r]=t[r])},remove:function(e,t){var n=this.data[e];n&&delete n[t]},removeAll:function(t,n){var r;n?e.each(n,function(e,n){this.remove(t,typeof n=="string"?n:e)},this):(r=this.data,t in r&&delete r[t])},get:function(e,t){var n=this.data[e];if(n)return n[t]},getAll:function(e,t){var n=this.data[e],r,i;if(t)i=n;else if(n){i={};for(r in n)n.hasOwnProperty(r)&&(i[r]=n[r])}return i}};var n=e.Object,r=e.Lang,i=".",s="getter",o="setter",u="readOnly",a="writeOnce",f="initOnly",l="validator",c="value",h="valueFn",p="lazyAdd",d="added",v="_bypassProxy",m="initializing",g="initValue",y="lazy",b="isLazyAdd",w;E.INVALID_VALUE={},w=E.INVALID_VALUE,E._ATTR_CFG=[o,s,l,c,h,a,u,p,v],E.prototype={_initAttrHost:function(t,n,r){this._state=new e.State,this._initAttrs(t,n,r)},addAttr:function(e,t,n){var r=this,i=r._state,s,o;t=t||{},n=p in t?t[p]:n;if(n&&!r.attrAdded(e))i.addAll(e,{lazy:t,added:!0});else if(!r.attrAdded(e)||i.get(e,b))o=c in t,o&&(s=t.value,delete t.value),t.added=!0,t.initializing=!0,i.addAll(e,t),o&&r.set(e,s),i.remove(e,m);return r},attrAdded:function(e){return!!this._state.get(e,d)},get:function(e){return this._getAttr(e)},_isLazyAttr:function(e){return this._state.get(e,y)},_addLazyAttr:function(e,t){var n=this._state,r=n.get(e,y);n.add(e,b,!0),n.remove(e,y),this.addAttr(e,r)},set:function(e,t){return this._setAttr(e,t)},_set:function(e,t){return this._setAttr(e,t,null,!0)},_setAttr:function(t,r,s,o){var u=!0,a=this._state,l=this._stateProxy,h,p,d,v,m,g,y;return t.indexOf(i)!==-1&&(d=t,v=t.split(i),t=v.shift()),this._isLazyAttr(t)&&this._addLazyAttr(t),h=a.getAll(t,!0)||{},p=!(c in h),l&&t in l&&!h._bypassProxy&&(p=!1),g=h.writeOnce,y=h.initializing,!p&&!o&&(g&&(u=!1),h.readOnly&&(u=!1)),!y&&!o&&g===f&&(u=!1),u&&(p||(m=this.get(t)),v&&(r=n.setValue(e.clone(m),v,r),r===undefined&&(u=!1)),u&&(!this._fireAttrChange||y?this._setAttrVal(t,d,m,r):this._fireAttrChange(t,d,m,r,s))),this},_getAttr:function(e){var t=this,r=e,o=t._state,u,a,f,l;return e.indexOf(i)!==-1&&(u=e.split(i),e=u.shift()),t._tCfgs&&t._tCfgs[e]&&(l={},l[e]=t._tCfgs[e],delete t._tCfgs[e],t._addAttrs(l,t._tVals)),t._isLazyAttr(e)&&t._addLazyAttr(e),f=t._getStateVal(e),a=o.get(e,s),a&&!a.call&&(a=this[a]),f=a?a.call(t,f,r):f,f=u?n.getValue(f,u):f,f},_getStateVal:function(e){var t=this._stateProxy;return t&&e in t&&!this._state.get(e,v)?t[e]:this._state.get(e,c)},_setStateVal:function(e,t){var n=this._stateProxy;n&&e in n&&!this._state.get(e,v)?n[e]=t:this._state.add(e,c,t)},_setAttrVal:function(e,t,n,i){var s=this,o=!0,u=this._state.getAll(e,!0)||{},a=u.validator,f=u.setter,l=u.initializing,c=this._getStateVal(e),h=t||e,p,d;return a&&(a.call||(a=this[a]),a&&(d=a.call(s,i,h),!d&&l&&(i=u.defaultValue,d=!0))),!a||d?(f&&(f.call||(f=this[f]),f&&(p=f.call(s,i,h),p===w?o=!1:p!==undefined&&(i=p))),o&&(!t&&i===c&&!r.isObject(i)?o=!1:(g in u||(u.initValue=i),s._setStateVal(e,i)))):o=!1,o},setAttrs:function(e){return this._setAttrs(e)},_setAttrs:function(e){var t;for(t in e)e.hasOwnProperty(t)&&this.set(t,e[t]);return this},getAttrs:function(e){return this._getAttrs(e)},_getAttrs:function(e){var t={},r,i,s,o=e===!0;if(!e||o)e=n.keys(this._state.data);for(i=0,s=e.length;i<s;i++){r=e[i];if(!o||this._getStateVal(r)!=this._state.get(r,g))t[r]=this.get(r)}return t},addAttrs:function(e,t,n){var r=this;return e&&(r._tCfgs=e,r._tVals=r._normAttrVals(t),r._addAttrs(e,r._tVals,n),r._tCfgs=r._tVals=null),r},_addAttrs:function(e,t,n){var r=this,i,s,o;for(i in e)e.hasOwnProperty(i)&&(s=e[i],s.defaultValue=s.value,o=r._getAttrInitVal(i,s,r._tVals),o!==undefined&&(s.value=o),r._tCfgs[i]&&delete r._tCfgs[i],r.addAttr(i,s,n))},_protectAttrs:function(t){if(t){t=e.merge(t);for(var n in t)t.hasOwnProperty(n)&&(t[n]=e.merge(t[n]))}return t},_normAttrVals:function(t){return t?e.merge(t):null},_getAttrInitVal:function(e,t,n){var r,i;return!t.readOnly&&n&&n.hasOwnProperty(e)?r=n[e]:(r=t.value,i=t.valueFn,i&&(i.call||(i=this[i]),i&&(r=i.call(this,e)))),r},_initAttrs:function(t,n,r){t=t||this.constructor.ATTRS;var i=e.Base,s=e.BaseCore,o=i&&e.instanceOf(this,i),u=!o&&s&&e.instanceOf(this,s);t&&!o&&!u&&this.addAttrs(this._protectAttrs(t),n,r)}},e.AttributeCore=E},"3.7.3",{requires:["oop"]});
diff --git a/js/yui3/attribute-events/attribute-events-min.js b/js/yui3/attribute-events/attribute-events-min.js
new file mode 100644
index 000000000..916bd7856
--- /dev/null
+++ b/js/yui3/attribute-events/attribute-events-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("attribute-events",function(e,t){function o(){this._ATTR_E_FACADE={},n.call(this,{emitFacade:!0})}var n=e.EventTarget,r="Change",i="broadcast",s="published";o._ATTR_CFG=[i],o.prototype={set:function(e,t,n){return this._setAttr(e,t,n)},_set:function(e,t,n){return this._setAttr(e,t,n,!0)},setAttrs:function(e,t){return this._setAttrs(e,t)},_setAttrs:function(e,t){var n;for(n in e)e.hasOwnProperty(n)&&this.set(n,e[n],t);return this},_fireAttrChange:function(t,n,o,u,a){var f=this,l=t+r,c=f._state,h,p,d;c.get(t,s)||(d={queuable:!1,defaultTargetOnly:!0,defaultFn:f._defAttrChangeFn,silent:!0},p=c.get(t,i),p!==undefined&&(d.broadcast=p),f.publish(l,d),c.add(t,s,!0)),h=a?e.merge(a):f._ATTR_E_FACADE,h.attrName=t,h.subAttrName=n,h.prevVal=o,h.newVal=u,f.fire(l,h)},_defAttrChangeFn:function(e){this._setAttrVal(e.attrName,e.subAttrName,e.prevVal,e.newVal)?e.newVal=this.get(e.attrName):e.stopImmediatePropagation()}},e.mix(o,n,!1,null,1),e.AttributeEvents=o},"3.7.3",{requires:["event-custom"]});
diff --git a/js/yui3/attribute-extras/attribute-extras-min.js b/js/yui3/attribute-extras/attribute-extras-min.js
new file mode 100644
index 000000000..6b268f0fc
--- /dev/null
+++ b/js/yui3/attribute-extras/attribute-extras-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("attribute-extras",function(e,t){function o(){}var n="broadcast",r="published",i="initValue",s={readOnly:1,writeOnce:1,getter:1,broadcast:1};o.prototype={modifyAttr:function(e,t){var i=this,o,u;if(i.attrAdded(e)){i._isLazyAttr(e)&&i._addLazyAttr(e),u=i._state;for(o in t)s[o]&&t.hasOwnProperty(o)&&(u.add(e,o,t[o]),o===n&&u.remove(e,r))}},removeAttr:function(e){this._state.removeAll(e)},reset:function(t){var n=this;return t?(n._isLazyAttr(t)&&n._addLazyAttr(t),n.set(t,n._state.get(t,i))):e.each(n._state.data,function(e,t){n.reset(t)}),n},_getAttrCfg:function(t){var n,r=this._state;return t?n=r.getAll(t)||{}:(n={},e.each(r.data,function(e,t){n[t]=r.getAll(t)})),n}},e.AttributeExtras=o},"3.7.3",{requires:["oop"]});
diff --git a/js/yui3/autocomplete-base/autocomplete-base-min.js b/js/yui3/autocomplete-base/autocomplete-base-min.js
new file mode 100644
index 000000000..f16c8c14d
--- /dev/null
+++ b/js/yui3/autocomplete-base/autocomplete-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-base",function(e,t){function T(){}var n=e.Escape,r=e.Lang,i=e.Array,s=e.Object,o=r.isFunction,u=r.isString,a=r.trim,f=e.Attribute.INVALID_VALUE,l="_functionValidator",c="_sourceSuccess",h="allowBrowserAutocomplete",p="inputNode",d="query",v="queryDelimiter",m="requestTemplate",g="results",y="resultListLocator",b="value",w="valueChange",E="clear",S=d,x=g;T.prototype={initializer:function(){e.before(this._bindUIACBase,this,"bindUI"),e.before(this._syncUIACBase,this,"syncUI"),this.publish(E,{defaultFn:this._defClearFn}),this.publish(S,{defaultFn:this._defQueryFn}),this.publish(x,{defaultFn:this._defResultsFn})},destructor:function(){this._acBaseEvents&&this._acBaseEvents.detach(),delete this._acBaseEvents,delete this._cache,delete this._inputNode,delete this._rawSource},clearCache:function(){return this._cache&&(this._cache={}),this},sendRequest:function(t,n){var r,i=this.get("source");return t||t===""?this._set(d,t):t=this.get(d)||"",i&&(n||(n=this.get(m)),r=n?n.call(this,t):t,i.sendRequest({query:t,request:r,callback:{success:e.bind(this._onResponse,this,t)}})),this},_bindUIACBase:function(){var t=this.get(p),n=t&&t.tokenInput;n&&(t=n.get(p),this._set("tokenInput",n));if(!t){e.error("No inputNode specified.");return}this._inputNode=t,this._acBaseEvents=new e.EventHandle([t.on(w,this._onInputValueChange,this),t.on("blur",this._onInputBlur,this),this.after(h+"Change",this._syncBrowserAutocomplete),this.after("sourceTypeChange",this._afterSourceTypeChange),this.after(w,this._afterValueChange)])},_syncUIACBase:function(){this._syncBrowserAutocomplete(),this.set(b,this.get(p).get(b))},_createArraySource:function(e){var t=this;return{type:"array",sendRequest:function(n){t[c](e.concat(),n)}}},_createFunctionSource:function(e){var t=this;return{type:"function",sendRequest:function(n){function i(e){t[c](e||[],n)}var r;(r=e(n.query,i))&&i(r)}}},_createObjectSource:function(e){var t=this;return{type:"object",sendRequest:function(n){var r=n.query;t[c](s.owns(e,r)?e[r]:[],n)}}},_functionValidator:function(e){return e===null||o(e)},_getObjectValue:function(e,t){if(!e)return;for(var n=0,r=t.length;e&&n<r;n++)e=e[t[n]];return e},_parseResponse:function(e,t,r){var i={data:r,query:e,results:[]},s=this.get(y),o=[],u=t&&t.results,a,f,l,c,h,p,d,v,m,g,b;u&&s&&(u=s.call(this,u));if(u&&u.length){a=this.get("resultFilters"),b=this.get("resultTextLocator");for(p=0,d=u.length;p<d;++p)m=u[p],g=b?b.call(this,m):m.toString(),o.push({display:n.html(g),raw:m,text:g});for(p=0,d=a.length;p<d;++p){o=a[p].call(this,e,o.concat());if(!o)return;if(!o.length)break}if(o.length){l=this.get("resultFormatter"),h=this.get("resultHighlighter"),v=this.get("maxResults"),v&&v>0&&o.length>v&&(o.length=v);if(h){c=h.call(this,e,o.concat());if(!c)return;for(p=0,d=c.length;p<d;++p)m=o[p],m.highlighted=c[p],m.display=m.highlighted}if(l){f=l.call(this,e,o.concat());if(!f)return;for(p=0,d=f.length;p<d;++p)o[p].display=f[p]}}}i.results=o,this.fire(x,i)},_parseValue:function(e){var t=this.get(v);return t&&(e=e.split(t),e=e[e.length-1]),r.trimLeft(e)},_setEnableCache:function(e){this._cache=e?{}:null},_setLocator:function(e){if(this[l](e))return e;var t=this;return e=e.toString().split("."),function(n){return n&&t._getObjectValue(n,e)}},_setRequestTemplate:function(e){return this[l](e)?e:(e=e.toString(),function(t){return r.sub(e,{query:encodeURIComponent(t)})})},_setResultFilters:function(t){var n,s;return t===null?[]:(n=e.AutoCompleteFilters,s=function(e){return o(e)?e:u(e)&&n&&o(n[e])?n[e]:!1},r.isArray(t)?(t=i.map(t,s),i.every(t,function(e){return!!e})?t:f):(t=s(t),t?[t]:f))},_setResultHighlighter:function(t){var n;return this[l](t)?t:(n=e.AutoCompleteHighlighters,u(t)&&n&&o(n[t])?n[t]:f)},_setSource:function(t){var n=this.get("sourceType")||r.type(t),i;return t&&o(t.sendRequest)||t===null||n==="datasource"?(this._rawSource=t,t):(i=T.SOURCE_TYPES[n])?(this._rawSource=t,r.isString(i)?this[i](t):i(t)):(e.error("Unsupported source type '"+n+"'. Maybe autocomplete-sources isn't loaded?"),f)},_sourceSuccess:function(e,t){t.callback.success({data:e,response:{results:e}})},_syncBrowserAutocomplete:function(){var e=this.get(p);e.get("nodeName").toLowerCase()==="input"&&e.setAttribute("autocomplete",this.get(h)?"on":"off")},_updateValue:function(e){var t=this.get(v),n,s,o;e=r.trimLeft(e),t&&(n=a(t),o=i.map(a(this.get(b)).split(t),a),s=o.length,s>1&&(o[s-1]=e,e=o.join(n+" ")),e=e+n+" "),this.set(b,e)},_afterSourceTypeChange:function(e){this._rawSource&&this.set("source",this._rawSource)},_afterValueChange:function(e){var t=e.newVal,n=this,r=e.src===T.UI_SRC,i,s,o,u;r||n._inputNode.set(b,t),o=n.get("minQueryLength"),u=n._parseValue(t)||"",o>=0&&u.length>=o?r?(i=n.get("queryDelay"),s=function(){n.fire(S,{inputValue:t,query:u,src:e.src})},i?(clearTimeout(n._delay),n._delay=setTimeout(s,i)):s()):n._set(d,u):(clearTimeout(n._delay),n.fire(E,{prevVal:e.prevVal?n._parseValue(e.prevVal):null,src:e.src}))},_onInputBlur:function(e){var t=this.get(v),n,i,s;if(t&&!this.get("allowTrailingDelimiter")){t=r.trimRight(t),s=i=this._inputNode.get(b);if(t)while((i=r.trimRight(i))&&(n=i.length-t.length)&&i.lastIndexOf(t)===n)i=i.substring(0,n);else i=r.trimRight(i);i!==s&&this.set(b,i)}},_onInputValueChange:function(e){var t=e.newVal;t!==this.get(b)&&this.set(b,t,{src:T.UI_SRC})},_onResponse:function(e,t){e===(this.get(d)||"")&&this._parseResponse(e||"",t.response,t.data)},_defClearFn:function(){this._set(d,null),this._set(g,[])},_defQueryFn:function(e){this.sendRequest(e.query)},_defResultsFn:function(e){this._set(g,e[g])}},T.ATTRS={allowBrowserAutocomplete:{value:!1},allowTrailingDelimiter:{value:!1},enableCache:{lazyAdd:!1,setter:"_setEnableCache",value:!0},inputNode:{setter:e.one,writeOnce:"initOnly"},maxResults:{value:0},minQueryLength:{value:1},query:{readOnly:!0,value:null},queryDelay:{value:100},queryDelimiter:{value:null},requestTemplate:{setter:"_setRequestTemplate",value:null},resultFilters:{setter:"_setResultFilters",value:[]},resultFormatter:{validator:l,value:null},resultHighlighter:{setter:"_setResultHighlighter",value:null},resultListLocator:{setter:"_setLocator",value:null},results:{readOnly:!0,value:[]},resultTextLocator:{setter:"_setLocator",value:null},source:{setter:"_setSource",value:null},sourceType:{value:null},tokenInput:{readOnly:!0},value:{value:""}},T._buildCfg={aggregates:["SOURCE_TYPES"],statics:["UI_SRC"]},T.SOURCE_TYPES={array:"_createArraySource","function":"_createFunctionSource",object:"_createObjectSource"},T.UI_SRC=e.Widget&&e.Widget.UI_SRC||"ui",e.AutoCompleteBase=T},"3.7.3",{optional:["autocomplete-sources"],requires:["array-extras","base-build","escape","event-valuechange","node-base"]});
diff --git a/js/yui3/autocomplete-filters-accentfold/autocomplete-filters-accentfold-min.js b/js/yui3/autocomplete-filters-accentfold/autocomplete-filters-accentfold-min.js
new file mode 100644
index 000000000..f4a998b81
--- /dev/null
+++ b/js/yui3/autocomplete-filters-accentfold/autocomplete-filters-accentfold-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-filters-accentfold",function(e,t){var n=e.Text.AccentFold,r=e.Text.WordBreak,i=e.Array,s=e.Object;e.mix(e.namespace("AutoCompleteFilters"),{charMatchFold:function(e,t){if(!e)return t;var r=i.unique(n.fold(e).split(""));return i.filter(t,function(e){var t=n.fold(e.text);return i.every(r,function(e){return t.indexOf(e)!==-1})})},phraseMatchFold:function(e,t){return e?(e=n.fold(e),i.filter(t,function(t){return n.fold(t.text).indexOf(e)!==-1})):t},startsWithFold:function(e,t){return e?(e=n.fold(e),i.filter(t,function(t){return n.fold(t.text).indexOf(e)===0})):t},subWordMatchFold:function(e,t){if(!e)return t;var s=r.getUniqueWords(n.fold(e));return i.filter(t,function(e){var t=n.fold(e.text);return i.every(s,function(e){return t.indexOf(e)!==-1})})},wordMatchFold:function(e,t){if(!e)return t;var o=r.getUniqueWords(n.fold(e));return i.filter(t,function(e){var t=i.hash(r.getUniqueWords(n.fold(e.text)));return i.every(o,function(e){return s.owns(t,e)})})}})},"3.7.3",{requires:["array-extras","text-accentfold","text-wordbreak"]});
diff --git a/js/yui3/autocomplete-filters/autocomplete-filters-min.js b/js/yui3/autocomplete-filters/autocomplete-filters-min.js
new file mode 100644
index 000000000..90ca1f71e
--- /dev/null
+++ b/js/yui3/autocomplete-filters/autocomplete-filters-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-filters",function(e,t){var n=e.Array,r=e.Object,i=e.Text.WordBreak,s=e.mix(e.namespace("AutoCompleteFilters"),{charMatch:function(e,t,r){if(!e)return t;var i=n.unique((r?e:e.toLowerCase()).split(""));return n.filter(t,function(e){return e=e.text,r||(e=e.toLowerCase()),n.every(i,function(t){return e.indexOf(t)!==-1})})},charMatchCase:function(e,t){return s.charMatch(e,t,!0)},phraseMatch:function(e,t,r){return e?(r||(e=e.toLowerCase()),n.filter(t,function(t){return(r?t.text:t.text.toLowerCase()).indexOf(e)!==-1})):t},phraseMatchCase:function(e,t){return s.phraseMatch(e,t,!0)},startsWith:function(e,t,r){return e?(r||(e=e.toLowerCase()),n.filter(t,function(t){return(r?t.text:t.text.toLowerCase()).indexOf(e)===0})):t},startsWithCase:function(e,t){return s.startsWith(e,t,!0)},subWordMatch:function(e,t,r){if(!e)return t;var s=i.getUniqueWords(e,{ignoreCase:!r});return n.filter(t,function(e){var t=r?e.text:e.text.toLowerCase();return n.every(s,function(e){return t.indexOf(e)!==-1})})},subWordMatchCase:function(e,t){return s.subWordMatch(e,t,!0)},wordMatch:function(e,t,s){if(!e)return t;var o={ignoreCase:!s},u=i.getUniqueWords(e,o);return n.filter(t,function(e){var t=n.hash(i.getUniqueWords(e.text,o));return n.every(u,function(e){return r.owns(t,e)})})},wordMatchCase:function(e,t){return s.wordMatch(e,t,!0)}})},"3.7.3",{requires:["array-extras","text-wordbreak"]});
diff --git a/js/yui3/autocomplete-highlighters-accentfold/autocomplete-highlighters-accentfold-min.js b/js/yui3/autocomplete-highlighters-accentfold/autocomplete-highlighters-accentfold-min.js
new file mode 100644
index 000000000..d40075946
--- /dev/null
+++ b/js/yui3/autocomplete-highlighters-accentfold/autocomplete-highlighters-accentfold-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-highlighters-accentfold",function(e,t){var n=e.Highlight,r=e.Array;e.mix(e.namespace("AutoCompleteHighlighters"),{charMatchFold:function(e,t){var i=r.unique(e.split(""));return r.map(t,function(e){return n.allFold(e.text,i)})},phraseMatchFold:function(e,t){return r.map(t,function(t){return n.allFold(t.text,[e])})},startsWithFold:function(e,t){return r.map(t,function(t){return n.allFold(t.text,[e],{startsWith:!0})})},subWordMatchFold:function(t,i){var s=e.Text.WordBreak.getUniqueWords(t);return r.map(i,function(e){return n.allFold(e.text,s)})},wordMatchFold:function(e,t){return r.map(t,function(t){return n.wordsFold(t.text,e)})}})},"3.7.3",{requires:["array-extras","highlight-accentfold"]});
diff --git a/js/yui3/autocomplete-highlighters/autocomplete-highlighters-min.js b/js/yui3/autocomplete-highlighters/autocomplete-highlighters-min.js
new file mode 100644
index 000000000..3b0bda57a
--- /dev/null
+++ b/js/yui3/autocomplete-highlighters/autocomplete-highlighters-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-highlighters",function(e,t){var n=e.Array,r=e.Highlight,i=e.mix(e.namespace("AutoCompleteHighlighters"),{charMatch:function(e,t,i){var s=n.unique((i?e:e.toLowerCase()).split(""));return n.map(t,function(e){return r.all(e.text,s,{caseSensitive:i})})},charMatchCase:function(e,t){return i.charMatch(e,t,!0)},phraseMatch:function(e,t,i){return n.map(t,function(t){return r.all(t.text,[e],{caseSensitive:i})})},phraseMatchCase:function(e,t){return i.phraseMatch(e,t,!0)},startsWith:function(e,t,i){return n.map(t,function(t){return r.all(t.text,[e],{caseSensitive:i,startsWith:!0})})},startsWithCase:function(e,t){return i.startsWith(e,t,!0)},subWordMatch:function(t,i,s){var o=e.Text.WordBreak.getUniqueWords(t,{ignoreCase:!s});return n.map(i,function(e){return r.all(e.text,o,{caseSensitive:s})})},subWordMatchCase:function(e,t){return i.subWordMatch(e,t,!0)},wordMatch:function(e,t,i){return n.map(t,function(t){return r.words(t.text,e,{caseSensitive:i})})},wordMatchCase:function(e,t){return i.wordMatch(e,t,!0)}})},"3.7.3",{requires:["array-extras","highlight-base"]});
diff --git a/js/yui3/autocomplete-list-keys/autocomplete-list-keys-min.js b/js/yui3/autocomplete-list-keys/autocomplete-list-keys-min.js
new file mode 100644
index 000000000..1ef5f46a0
--- /dev/null
+++ b/js/yui3/autocomplete-list-keys/autocomplete-list-keys-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-list-keys",function(e,t){function u(){e.before(this._bindKeys,this,"bindUI"),this._initKeys()}var n=40,r=13,i=27,s=9,o=38;u.prototype={_initKeys:function(){var e={},t={};e[n]=this._keyDown,t[r]=this._keyEnter,t[i]=this._keyEsc,t[s]=this._keyTab,t[o]=this._keyUp,this._keys=e,this._keysVisible=t},destructor:function(){this._unbindKeys()},_bindKeys:function(){this._keyEvents=this._inputNode.on("keydown",this._onInputKey,this)},_unbindKeys:function(){this._keyEvents&&this._keyEvents.detach(),this._keyEvents=null},_keyDown:function(){this.get("visible")?this._activateNextItem():this.show()},_keyEnter:function(e){var t=this.get("activeItem");if(!t)return!1;this.selectItem(t,e)},_keyEsc:function(){this.hide()},_keyTab:function(e){var t;if(this.get("tabSelect")){t=this.get("activeItem");if(t)return this.selectItem(t,e),!0}return!1},_keyUp:function(){this._activatePrevItem()},_onInputKey:function(e){var t,n=e.keyCode;this._lastInputKey=n,this.get("results").length&&(t=this._keys[n],!t&&this.get("visible")&&(t=this._keysVisible[n]),t&&t.call(this,e)!==!1&&e.preventDefault())}},e.Base.mix(e.AutoCompleteList,[u])},"3.7.3",{requires:["autocomplete-list","base-build"]});
diff --git a/js/yui3/autocomplete-list/assets/autocomplete-list-core.css b/js/yui3/autocomplete-list/assets/autocomplete-list-core.css
new file mode 100644
index 000000000..a4f88d5d3
--- /dev/null
+++ b/js/yui3/autocomplete-list/assets/autocomplete-list-core.css
@@ -0,0 +1,33 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-aclist {
+ position: absolute;
+ z-index: 1;
+}
+
+.yui3-aclist-hidden { visibility: hidden; }
+
+.yui3-aclist-aria {
+ /* Hide from sighted users, show to screen readers. */
+ left: -9999px;
+ position: absolute;
+}
+
+.yui3-aclist-list {
+ list-style: none;
+ margin: 0;
+ overflow: hidden;
+ padding: 0;
+}
+
+.yui3-aclist-item {
+ cursor: pointer;
+ list-style: none;
+ padding: 2px 5px;
+}
+
+.yui3-aclist-item-active { outline: #afafaf dotted thin; }
diff --git a/js/yui3/autocomplete-list/assets/skins/night/autocomplete-list.css b/js/yui3/autocomplete-list/assets/skins/night/autocomplete-list.css
new file mode 100644
index 000000000..6fc5947f6
--- /dev/null
+++ b/js/yui3/autocomplete-list/assets/skins/night/autocomplete-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-aclist{position:absolute;z-index:1}.yui3-aclist-hidden{visibility:hidden}.yui3-aclist-aria{left:-9999px;position:absolute}.yui3-aclist-list{list-style:none;margin:0;overflow:hidden;padding:0}.yui3-aclist-item{cursor:pointer;list-style:none;padding:2px 5px}.yui3-aclist-item-active{outline:#afafaf dotted thin}.yui3-skin-night [for=ac-input]{color:#cbcbcb}.yui3-skin-night .yui3-aclist-content{font-size:100%;background-color:#151515;color:#ccc;border:1px solid #303030;-moz-box-shadow:0 0 17px rgba(0,0,0,0.58);-webkit-box-shadow:0 0 17px rgba(0,0,0,0.58);box-shadow:0 0 17px rgba(0,0,0,0.58)}.yui3-skin-night .yui3-aclist-item-active{background-color:#2f3030;background:-moz-linear-gradient(0% 100% 90deg,#252626 0,#333434 100%);background:-webkit-gradient(linear,left top,left bottom,from(#333434),to(#252626))}.yui3-skin-night .yui3-aclist-item-hover{background-color:#262727;background:-moz-linear-gradient(0% 100% 90deg,#202121 0,#282929 100%);background:-webkit-gradient(linear,left top,left bottom,from(#282929),to(#202121))}.yui3-skin-night .yui3-aclist-item{padding:0 1em;line-height:2.25}.yui3-skin-night .yui3-aclist-item-active{outline:0}.yui3-skin-night .yui3-highlight{color:#efefef}#yui3-css-stamp.skin-night-autocomplete-list{display:none}
diff --git a/js/yui3/autocomplete-list/assets/skins/sam/autocomplete-list.css b/js/yui3/autocomplete-list/assets/skins/sam/autocomplete-list.css
new file mode 100644
index 000000000..68b350911
--- /dev/null
+++ b/js/yui3/autocomplete-list/assets/skins/sam/autocomplete-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-aclist{position:absolute;z-index:1}.yui3-aclist-hidden{visibility:hidden}.yui3-aclist-aria{left:-9999px;position:absolute}.yui3-aclist-list{list-style:none;margin:0;overflow:hidden;padding:0}.yui3-aclist-item{cursor:pointer;list-style:none;padding:2px 5px}.yui3-aclist-item-active{outline:#afafaf dotted thin}.yui3-skin-sam .yui3-aclist-content{background:#fff;border:1px solid #afafaf;-moz-box-shadow:1px 1px 4px rgba(0,0,0,0.58);-webkit-box-shadow:1px 1px 4px rgba(0,0,0,0.58);box-shadow:1px 1px 4px rgba(0,0,0,0.58)}.yui3-skin-sam .yui3-aclist-item-hover{background:#bfdaff}.yui3-skin-sam .yui3-aclist-item-active{background:#2647a0;color:#fff;outline:0}#yui3-css-stamp.skin-sam-autocomplete-list{display:none}
diff --git a/js/yui3/autocomplete-list/autocomplete-list-min.js b/js/yui3/autocomplete-list/autocomplete-list-min.js
new file mode 100644
index 000000000..7d07d24e1
--- /dev/null
+++ b/js/yui3/autocomplete-list/autocomplete-list-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-list",function(e,t){var n=e.Lang,r=e.Node,i=e.Array,s=e.UA.ie&&e.UA.ie<7,o=9,u="_CLASS_ITEM",a="_CLASS_ITEM_ACTIVE",f="_CLASS_ITEM_HOVER",l="_SELECTOR_ITEM",c="activeItem",h="alwaysShowList",p="circular",d="hoveredItem",v="id",m="item",g="list",y="result",b="results",w="visible",E="width",S="select",x=e.Base.create("autocompleteList",e.Widget,[e.AutoCompleteBase,e.WidgetPosition,e.WidgetPositionAlign],{ARIA_TEMPLATE:"<div/>",ITEM_TEMPLATE:"<li/>",LIST_TEMPLATE:"<ul/>",UI_EVENTS:function(){var t=e.merge(e.Node.DOM_EVENTS);return delete t.valuechange,delete t.valueChange,t}(),initializer:function(){var t=this.get("inputNode");if(!t){e.error("No inputNode specified.");return}this._inputNode=t,this._listEvents=[],this.DEF_PARENT_NODE=t.get("parentNode"),this[u]=this.getClassName(m),this[a]=this.getClassName(m,"active"),this[f]=this.getClassName(m,"hover"),this[l]="."+this[u],this.publish(S,{defaultFn:this._defSelectFn})},destructor:function(){while(this._listEvents.length)this._listEvents.pop().detach();this._ariaNode&&this._ariaNode.remove().destroy(!0)},bindUI:function(){this._bindInput(),this._bindList()},renderUI:function(){var t=this._createAriaNode(),n=this.get("boundingBox"),r=this.get("contentBox"),i=this._inputNode,o=this._createListNode(),u=i.get("parentNode");i.addClass(this.getClassName("input")).setAttrs({"aria-autocomplete":g,"aria-expanded":!1,"aria-owns":o.get("id")}),u.append(t),s&&n.plug(e.Plugin.Shim),n.setStyle("position","absolute"),this._ariaNode=t,this._boundingBox=n,this._contentBox=r,this._listNode=o,this._parentNode=u},syncUI:function(){this._syncResults(),this._syncVisibility()},hide:function(){return this.get(h)?this:this.set(w,!1)},selectItem:function(e,t){if(e){if(!e.hasClass(this[u]))return this}else{e=this.get(c);if(!e)return this}return this.fire(S,{itemNode:e,originEvent:t||null,result:e.getData(y)}),this},_activateNextItem:function(){var e=this.get(c),t;return e?t=e.next(this[l])||(this.get(p)?null:e):t=this._getFirstItemNode(),this.set(c,t),this},_activatePrevItem:function(){var e=this.get(c),t=e?e.previous(this[l]):this.get(p)&&this._getLastItemNode();return this.set(c,t||null),this},_add:function(t){var r=[];return i.each(n.isArray(t)?t:[t],function(e){r.push(this._createItemNode(e).setData(y,e))},this),r=e.all(r),this._listNode.append(r.toFrag()),r},_ariaSay:function(e,t){var r=this.get("strings."+e);this._ariaNode.set("text",t?n.sub(r,t):r)},_bindInput:function(){var e=this._inputNode,t,n,r;this.get("align")===null&&(r=this.get("tokenInput"),t=r&&r.get("boundingBox")||e,this.set("align",{node:t,points:["tl","bl"]}),!this.get(E)&&(n=t.get("offsetWidth"))&&this.set(E,n)),this._listEvents=this._listEvents.concat([e.after("blur",this._afterListInputBlur,this),e.after("focus",this._afterListInputFocus,this)])},_bindList:function(){this._listEvents=this._listEvents.concat([e.one("doc").after("click",this._afterDocClick,this),e.one("win").after("windowresize",this._syncPosition,this),this.after({mouseover:this._afterMouseOver,mouseout:this._afterMouseOut,activeItemChange:this._afterActiveItemChange,alwaysShowListChange:this._afterAlwaysShowListChange,hoveredItemChange:this._afterHoveredItemChange,resultsChange:this._afterResultsChange,visibleChange:this._afterVisibleChange}),this._listNode.delegate("click",this._onItemClick,this[l],this)])},_clear:function(){this.set(c,null),this._set(d,null),this._listNode.get("children").remove(!0)},_createAriaNode:function(){var e=r.create(this.ARIA_TEMPLATE);return e.addClass(this.getClassName("aria")).setAttrs({"aria-live":"polite",role:"status"})},_createItemNode:function(t){var n=r.create(this.ITEM_TEMPLATE);return n.addClass(this[u]).setAttrs({id:e.stamp(n),role:"option"}).setAttribute("data-text",t.text).append(t.display)},_createListNode:function(){var t=this.get("listNode")||r.create(this.LIST_TEMPLATE);return t.addClass(this.getClassName(g)).setAttrs({id:e.stamp(t),role:"listbox"}),this._set("listNode",t),this.get("contentBox").append(t),t},_getFirstItemNode:function(){return this._listNode.one(this[l])},_getLastItemNode:function(){return this._listNode.one(this[l]+":last-child")},_syncPosition:function(){this._syncUIPosAlign(),this._syncShim()},_syncResults:function(e){e||(e=this.get(b)),this._clear(),e.length&&(this._add(e),this._ariaSay("items_available")),this._syncPosition(),this.get("activateFirstItem")&&!this.get(c)&&this.set(c,this._getFirstItemNode())},_syncShim:s?function(){var e=this._boundingBox.shim;e&&e.sync()}:function(){},_syncVisibility:function(t){this.get(h)&&(t=!0,this.set(w,t)),typeof t=="undefined"&&(t=this.get(w)),this._inputNode.set("aria-expanded",t),this._boundingBox.set("aria-hidden",!t),t?this._syncPosition():(this.set(c,null),this._set(d,null),this._boundingBox.get("offsetWidth")),e.UA.ie===7&&e.one("body").addClass("yui3-ie7-sucks").removeClass("yui3-ie7-sucks")},_afterActiveItemChange:function(t){var n=this._inputNode,r=t.newVal,i=t.prevVal,s;i&&i._node&&i.removeClass(this[a]),r?(r.addClass(this[a]),n.set("aria-activedescendant",r.get(v))):n.removeAttribute("aria-activedescendant"),this.get("scrollIntoView")&&(s=r||n,(!s.inRegion(e.DOM.viewportRegion(),!0)||!s.inRegion(this._contentBox,!0))&&s.scrollIntoView())},_afterAlwaysShowListChange:function(e){this.set(w,e.newVal||this.get(b).length>0)},_afterDocClick:function(e){var t=this._boundingBox,n=e.target;n!==this._inputNode&&n!==t&&n.ancestor("#"+t.get("id"),!0)&&this.hide()},_afterHoveredItemChange:function(e){var t=e.newVal,n=e.prevVal;n&&n.removeClass(this[f]),t&&t.addClass(this[f])},_afterListInputBlur:function(){this._listInputFocused=!1,this.get(w)&&!this._mouseOverList&&(this._lastInputKey!==o||!this.get("tabSelect")||!this.get(c))&&this.hide()},_afterListInputFocus:function(){this._listInputFocused=!0},_afterMouseOver:function(e){var t=e.domEvent.target.ancestor(this[l],!0);this._mouseOverList=!0,t&&this._set(d,t)},_afterMouseOut:function(){this._mouseOverList=!1,this._set(d,null)},_afterResultsChange:function(e){this._syncResults(e.newVal),this.get(h)||this.set(w,!!e.newVal.length)},_afterVisibleChange:function(e){this._syncVisibility(!!e.newVal)},_onItemClick:function(e){var t=e.currentTarget;this.set(c,t),this.selectItem(t,e)},_defSelectFn:function(e){var t=e.result.text;this._inputNode.focus(),this._updateValue(t),this._ariaSay("item_selected",{item:t}),this.hide()}},{ATTRS:{activateFirstItem:{value:!1},activeItem:{setter:e.one,value:null},alwaysShowList:{value:!1},circular:{value:!0},hoveredItem:{readOnly:!0,value:null},listNode:{writeOnce:"initOnly",value:null},scrollIntoView:{value:!1},strings:{valueFn:function(){return e.Intl.get("autocomplete-list")}},tabSelect:{value:!0},visible:{value:!1}},CSS_PREFIX:e.ClassNameManager.getClassName("aclist")});e.AutoCompleteList=x,e.AutoComplete=x},"3.7.3",{lang:["en"],requires:["autocomplete-base","event-resize","node-screen","selector-css3","shim-plugin","widget","widget-position","widget-position-align"],skinnable:!0});
diff --git a/js/yui3/autocomplete-list/lang/autocomplete-list.js b/js/yui3/autocomplete-list/lang/autocomplete-list.js
new file mode 100644
index 000000000..f5f34759c
--- /dev/null
+++ b/js/yui3/autocomplete-list/lang/autocomplete-list.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/autocomplete-list",function(e){e.Intl.add("autocomplete-list","",{item_selected:"{item} selected.",items_available:"Suggestions are available. Use the up and down arrow keys to select suggestions."})},"3.7.3");
diff --git a/js/yui3/autocomplete-list/lang/autocomplete-list_en.js b/js/yui3/autocomplete-list/lang/autocomplete-list_en.js
new file mode 100644
index 000000000..469aab200
--- /dev/null
+++ b/js/yui3/autocomplete-list/lang/autocomplete-list_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/autocomplete-list_en",function(e){e.Intl.add("autocomplete-list","en",{item_selected:"{item} selected.",items_available:"Suggestions are available. Use up and down arrows to select."})},"3.7.3");
diff --git a/js/yui3/autocomplete-plugin/autocomplete-plugin-min.js b/js/yui3/autocomplete-plugin/autocomplete-plugin-min.js
new file mode 100644
index 000000000..61bf97b7c
--- /dev/null
+++ b/js/yui3/autocomplete-plugin/autocomplete-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-plugin",function(e,t){function r(e){e.inputNode=e.host,!e.render&&e.render!==!1&&(e.render=!0),r.superclass.constructor.apply(this,arguments)}var n=e.Plugin;e.extend(r,e.AutoCompleteList,{},{NAME:"autocompleteListPlugin",NS:"ac",CSS_PREFIX:e.ClassNameManager.getClassName("aclist")}),n.AutoComplete=r,n.AutoCompleteList=r},"3.7.3",{requires:["autocomplete-list","node-pluginhost"]});
diff --git a/js/yui3/autocomplete-sources/autocomplete-sources-min.js b/js/yui3/autocomplete-sources/autocomplete-sources-min.js
new file mode 100644
index 000000000..214b6eca5
--- /dev/null
+++ b/js/yui3/autocomplete-sources/autocomplete-sources-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("autocomplete-sources",function(e,t){var n=e.AutoCompleteBase,r=e.Lang,i="_sourceSuccess",s="maxResults",o="requestTemplate",u="resultListLocator";e.mix(n.prototype,{_YQL_SOURCE_REGEX:/^(?:select|set|use)\s+/i,_beforeCreateObjectSource:function(t){return t instanceof e.Node&&t.get("nodeName").toLowerCase()==="select"?this._createSelectSource(t):e.JSONPRequest&&t instanceof e.JSONPRequest?this._createJSONPSource(t):this._createObjectSource(t)},_createIOSource:function(t){function a(n){var o=n.request;if(r._cache&&o in r._cache){r[i](r._cache[o],n);return}s&&s.isInProgress()&&s.abort(),s=e.io(r._getXHRUrl(t,n),{on:{success:function(t,s){var u;try{u=e.JSON.parse(s.responseText)}catch(a){e.error("JSON parse error",a)}u&&(r._cache&&(r._cache[o]=u),r[i](u,n))}}})}var n={type:"io"},r=this,s,o,u;return n.sendRequest=function(t){o=t;if(u)return;u=!0,e.use("io-base","json-parse",function(){n.sendRequest=a,a(o)})},n},_createJSONPSource:function(t){function u(e){var n=e.request,s=e.query;if(r._cache&&n in r._cache){r[i](r._cache[n],e);return}t._config.on.success=function(t){r._cache&&(r._cache[n]=t),r[i](t,e)},t.send(s)}var n={type:"jsonp"},r=this,s,o;return n.sendRequest=function(i){s=i;if(o)return;o=!0,e.use("jsonp",function(){t instanceof e.JSONPRequest||(t=new e.JSONPRequest(t,{format:e.bind(r._jsonpFormatter,r)})),n.sendRequest=u,u(s)})},n},_createSelectSource:function(e){var t=this;return{type:"select",sendRequest:function(n){var r=[];e.get("options").each(function(e){r.push({html:e.get("innerHTML"),index:e.get("index"),node:e,selected:e.get("selected"),text:e.get("text"),value:e.get("value")})}),t[i](r,n)}}},_createStringSource:function(e){return this._YQL_SOURCE_REGEX.test(e)?this._createYQLSource(e):e.indexOf("{callback}")!==-1?this._createJSONPSource(e):this._createIOSource(e)},_createYQLSource:function(t){function c(o){var u=o.query,a=n.get("yqlEnv"),f=n.get(s),c,h,p;p=r.sub(t,{maxResults:f>0?f:1e3,request:o.request,query:u});if(n._cache&&p in n._cache){n[i](n._cache[p],o);return}c=function(e){n._cache&&(n._cache[p]=e),n[i](e,o)},h={proto:n.get("yqlProtocol")},l?(l._callback=c,l._opts=h,l._params.q=p,a&&(l._params.env=a)):l=new e.YQLRequest(p,{on:{success:c},allowCache:!1},a?{env:a}:null,h),l.send()}var n=this,o={type:"yql"},a,f,l;return n.get(u)||n.set(u,n._defaultYQLLocator),o.sendRequest=function(t){a=t,f||(f=!0,e.use("yql",function(){o.sendRequest=c,c(a)}))},o},_defaultYQLLocator:function(t){var n=t&&t.query&&t.query.results,i;return n&&r.isObject(n)?(i=e.Object.values(n)||[],n=i.length===1?i[0]:i,r.isArray(n)||(n=[n])):n=[],n},_getXHRUrl:function(e,t){var n=this.get(s);return t.query!==t.request&&(e+=t.request),r.sub(e,{maxResults:n>0?n:1e3,query:encodeURIComponent(t.query)})},_jsonpFormatter:function(e,t,n){var i=this.get(s),u=this.get(o);return u&&(e+=u(n)),r.sub(e,{callback:t,maxResults:i>0?i:1e3,query:encodeURIComponent(n)})}}),e.mix(n.ATTRS,{yqlEnv:{value:null},yqlProtocol:{value:"http"}}),e.mix(n.SOURCE_TYPES,{io:"_createIOSource",jsonp:"_createJSONPSource",object:"_beforeCreateObjectSource",select:"_createSelectSource",string:"_createStringSource",yql:"_createYQLSource"},!0)},"3.7.3",{optional:["io-base","json-parse","jsonp","yql"],requires:["autocomplete-base"]});
diff --git a/js/yui3/base-base/base-base-min.js b/js/yui3/base-base/base-base-min.js
new file mode 100644
index 000000000..e49331d44
--- /dev/null
+++ b/js/yui3/base-base/base-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("base-base",function(e,t){function l(){u.apply(this,arguments)}var n=e.Lang,r="destroy",i="init",s="bubbleTargets",o="_bubbleTargets",u=e.BaseCore,a=e.AttributeCore,f=e.Attribute;l._ATTR_CFG=f._ATTR_CFG.concat("cloneDefaultValue"),l._ATTR_CFG_HASH=e.Array.hash(l._ATTR_CFG),l._NON_ATTRS_CFG=u._NON_ATTRS_CFG.concat(["on","after","bubbleTargets"]),l.NAME="base",l.ATTRS=a.prototype._protectAttrs(u.ATTRS),l.prototype={_initBase:function(t){this._eventPrefix=this.constructor.EVENT_PREFIX||this.constructor.NAME,e.BaseCore.prototype._initBase.call(this,t)},_initAttribute:function(e){f.call(this),this._yuievt.config.prefix=this._eventPrefix},_attrCfgHash:function(){return l._ATTR_CFG_HASH},init:function(e){return this.publish(i,{queuable:!1,fireOnce:!0,defaultTargetOnly:!0,defaultFn:this._defInitFn}),this._preInitEventCfg(e),this.fire(i,{cfg:e}),this},_preInitEventCfg:function(e){e&&(e.on&&this.on(e.on),e.after&&this.after(e.after));var t,r,i,u=e&&s in e;if(u||o in this){i=u?e&&e.bubbleTargets:this._bubbleTargets;if(n.isArray(i))for(t=0,r=i.length;t<r;t++)this.addTarget(i[t]);else i&&this.addTarget(i)}},destroy:function(){return this.publish(r,{queuable:!1,fireOnce:!0,defaultTargetOnly:!0,defaultFn:this._defDestroyFn}),this.fire(r),this.detachAll(),this},_defInitFn:function(e){this._baseInit(e.cfg)},_defDestroyFn:function(e){this._baseDestroy(e.cfg)}},e.mix(l,f,!1,null,1),e.mix(l,u,!1,null,1),l.prototype.constructor=l,e.Base=l},"3.7.3",{requires:["base-core","attribute-base"]});
diff --git a/js/yui3/base-build/base-build-min.js b/js/yui3/base-build/base-build-min.js
new file mode 100644
index 000000000..1d959d27e
--- /dev/null
+++ b/js/yui3/base-build/base-build-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("base-build",function(e,t){var n=e.Base,r=e.Lang,i="initializer",s="destructor",o,u=function(e,t,n){n[e]&&(t[e]=(t[e]||[]).concat(n[e]))};n._build=function(t,r,o,u,a,f){var l=n._build,c=l._ctor(r,f),h=l._cfg(r,f,o),p=l._mixCust,d=c._yuibuild.dynamic,v,m,g,y,b,w;for(v=0,m=o.length;v<m;v++)g=o[v],y=g.prototype,b=y[i],w=y[s],delete y[i],delete y[s],e.mix(c,g,!0,null,1),p(c,g,h),b&&(y[i]=b),w&&(y[s]=w),c._yuibuild.exts.push(g);return u&&e.mix(c.prototype,u,!0),a&&(e.mix(c,l._clean(a,h),!0),p(c,a,h)),c.prototype.hasImpl=l._impl,d&&(c.NAME=t,c.prototype.constructor=c),c},o=n._build,e.mix(o,{_mixCust:function(t,n,i){var s,o,u,a,f,l;i&&(s=i.aggregates,o=i.custom,u=i.statics),u&&e.mix(t,n,!0,u);if(s)for(l=0,f=s.length;l<f;l++)a=s[l],!t.hasOwnProperty(a)&&n.hasOwnProperty(a)&&(t[a]=r.isArray(n[a])?[]:{}),e.aggregate(t,n,!0,[a]);if(o)for(l in o)o.hasOwnProperty(l)&&o[l](l,t,n)},_tmpl:function(t){function n(){n.superclass.constructor.apply(this,arguments)}return e.extend(n,t),n},_impl:function(e){var t=this._getClasses(),n,r,i,s,o,u;for(n=0,r=t.length;n<r;n++){i=t[n];if(i._yuibuild){s=i._yuibuild.exts,o=s.length;for(u=0;u<o;u++)if(s[u]===e)return!0}}return!1},_ctor:function(e,t){var n=t&&!1===t.dynamic?!1:!0,r=n?o._tmpl(e):e,i=r._yuibuild;return i||(i=r._yuibuild={}),i.id=i.id||null,i.exts=i.exts||[],i.dynamic=n,r},_cfg:function(t,n,r){var i=[],s={},o=[],u,a=n&&n.aggregates,f=n&&n.custom,l=n&&n.statics,c=t,h,p;while(c&&c.prototype)u=c._buildCfg,u&&(u.aggregates&&(i=i.concat(u.aggregates)),u.custom&&e.mix(s,u.custom,!0),u.statics&&(o=o.concat(u.statics))),c=c.superclass?c.superclass.constructor:null;if(r)for(h=0,p=r.length;h<p;h++)c=r[h],u=c._buildCfg,u&&(u.aggregates&&(i=i.concat(u.aggregates)),u.custom&&e.mix(s,u.custom,!0),u.statics&&(o=o.concat(u.statics)));return a&&(i=i.concat(a)),f&&e.mix(s,n.cfgBuild,!0),l&&(o=o.concat(l)),{aggregates:i,custom:s,statics:o}},_clean:function(t,n){var r,i,s,o=e.merge(t),u=n.aggregates,a=n.custom;for(r in a)o.hasOwnProperty(r)&&delete o[r];for(i=0,s=u.length;i<s;i++)r=u[i],o.hasOwnProperty(r)&&delete o[r];return o}}),n.build=function(e,t,n,r){return o(e,t,n,null,null,r)},n.create=function(e,t,n,r,i){return o(e,t,n,r,i)},n.mix=function(e,t){return o(null,e,t,null,null,{dynamic:!1})},n._buildCfg={custom:{ATTRS:function(t,n,r){n.ATTRS=n.ATTRS||{};if(r.ATTRS){var i=r.ATTRS,s=n.ATTRS,o;for(o in i)i.hasOwnProperty(o)&&(s[o]=s[o]||{},e.mix(s[o],i[o],!0))}},_NON_ATTRS_CFG:u},aggregates:["_PLUG","_UNPLUG"]}},"3.7.3",{requires:["base-base"]});
diff --git a/js/yui3/base-core/base-core-min.js b/js/yui3/base-core/base-core-min.js
new file mode 100644
index 000000000..84f4b8aca
--- /dev/null
+++ b/js/yui3/base-core/base-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("base-core",function(e,t){function v(e){this._BaseInvoked||(this._BaseInvoked=!0,this._initBase(e))}var n=e.Object,r=e.Lang,i=".",s="initialized",o="destroyed",u="initializer",a="value",f=Object.prototype.constructor,l="deep",c="shallow",h="destructor",p=e.AttributeCore,d=function(e,t,n){var r;for(r in t)n[r]&&(e[r]=t[r]);return e};v._ATTR_CFG=p._ATTR_CFG.concat("cloneDefaultValue"),v._ATTR_CFG_HASH=e.Array.hash(v._ATTR_CFG),v._NON_ATTRS_CFG=["plugins"],v.NAME="baseCore",v.ATTRS={initialized:{readOnly:!0,value:!1},destroyed:{readOnly:!0,value:!1}},v.prototype={_initBase:function(t){e.stamp(this),this._initAttribute(t);var n=e.Plugin&&e.Plugin.Host;this._initPlugins&&n&&n.call(this),this._lazyAddAttrs!==!1&&(this._lazyAddAttrs=!0),this.name=this.constructor.NAME,this.init.apply(this,arguments)},_initAttribute:function(){p.apply(this)},init:function(e){return this._baseInit(e),this},_baseInit:function(e){this._initHierarchy(e),this._initPlugins&&this._initPlugins(e),this._set(s,!0)},destroy:function(){return this._baseDestroy(),this},_baseDestroy:function(){this._destroyPlugins&&this._destroyPlugins(),this._destroyHierarchy(),this._set(o,!0)},_getClasses:function(){return this._classes||this._initHierarchyData(),this._classes},_getAttrCfgs:function(){return this._attrs||this._initHierarchyData(),this._attrs},_filterAttrCfgs:function(e,t){var n=null,r,i=e.ATTRS;if(i)for(r in i)t[r]&&(n=n||{},n[r]=t[r],t[r]=null);return n},_filterAdHocAttrs:function(e,t){var n,r=this._nonAttrs,i;if(t){n={};for(i in t)!e[i]&&!r[i]&&t.hasOwnProperty(i)&&(n[i]={value:t[i]})}return n},_initHierarchyData:function(){var e=this.constructor,t,n,r,i=this._allowAdHocAttrs?{}:null,s=[],o=[];while(e){s[s.length]=e,e.ATTRS&&(o[o.length]=e.ATTRS);if(this._allowAdHocAttrs){r=e._NON_ATTRS_CFG;if(r)for(t=0,n=r.length;t<n;t++)i[r[t]]=!0}e=e.superclass?e.superclass.constructor:null}this._classes=s,this._nonAttrs=i,this._attrs=this._aggregateAttrs(o)},_attrCfgHash:function(){return v._ATTR_CFG_HASH},_aggregateAttrs:function(t){var s,o,u,h,p,v,m,g=this._attrCfgHash(),y,b={};if(t)for(v=t.length-1;v>=0;--v){o=t[v];for(s in o)o.hasOwnProperty(s)&&(u=d({},o[s],g),h=u.value,m=u.cloneDefaultValue,h&&(m===undefined&&(f===h.constructor||r.isArray(h))||m===l||m===!0?u.value=e.clone(h):m===c&&(u.value=e.merge(h))),p=null,s.indexOf(i)!==-1&&(p=s.split(i),s=p.shift()),y=b[s],p&&y&&y.value?n.setValue(y.value,p,h):p||(y?(y.valueFn&&a in u&&(y.valueFn=null),d(y,u,g)):b[s]=u))}return b},_initHierarchy:function(e){var t=this._lazyAddAttrs,n,r,i,s,o,a,f,l=this._getClasses(),c=this._getAttrCfgs(),h=l.length-1;for(i=h;i>=0;i--){n=l[i],r=n.prototype,f=n._yuibuild&&n._yuibuild.exts;if(f)for(s=0,o=f.length;s<o;s++)f[s].apply(this,arguments);this.addAttrs(this._filterAttrCfgs(n,c),e,t),this._allowAdHocAttrs&&i===h&&this.addAttrs(this._filterAdHocAttrs(c,e),e,t),r.hasOwnProperty(u)&&r.initializer.apply(this,arguments);if(f)for(s=0;s<o;s++)a=f[s].prototype,a.hasOwnProperty(u)&&a.initializer.apply(this,arguments)}},_destroyHierarchy:function(){var e,t,n,r,i,s,o,u,a=this._getClasses();for(n=0,r=a.length;n<r;n++){e=a[n],t=e.prototype,o=e._yuibuild&&e._yuibuild.exts;if(o)for(i=0,s=o.length;i<s;i++)u=o[i].prototype,u.hasOwnProperty(h)&&u.destructor.apply(this,arguments);t.hasOwnProperty(h)&&t.destructor.apply(this,arguments)}},toString:function(){return this.name+"["+e.stamp(this,!0)+"]"}},e.mix(v,p,!1,null,1),v.prototype.constructor=v,e.BaseCore=v},"3.7.3",{requires:["attribute-core"]});
diff --git a/js/yui3/base-pluginhost/base-pluginhost-min.js b/js/yui3/base-pluginhost/base-pluginhost-min.js
new file mode 100644
index 000000000..178471794
--- /dev/null
+++ b/js/yui3/base-pluginhost/base-pluginhost-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("base-pluginhost",function(e,t){var n=e.Base,r=e.Plugin.Host;e.mix(n,r,!1,null,1),n.plug=r.plug,n.unplug=r.unplug},"3.7.3",{requires:["base-base","pluginhost"]});
diff --git a/js/yui3/button-core/button-core-min.js b/js/yui3/button-core/button-core-min.js
new file mode 100644
index 000000000..d438ca71d
--- /dev/null
+++ b/js/yui3/button-core/button-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("button-core",function(e,t){function r(e){this.initializer(e)}var n=e.ClassNameManager.getClassName;r.prototype={TEMPLATE:"<button/>",constructor:r,initializer:function(e){this._initNode(e),this._initAttributes(e),this._renderUI(e)},_initNode:function(t){t.host?this._host=e.one(t.host):this._host=e.Node.create(this.TEMPLATE)},_initAttributes:function(t){var n=this._host,i=n.one("."+r.CLASS_NAMES.LABEL)||n;t.label=t.label||this._getLabel(i),e.AttributeCore.call(this,r.ATTRS,t)},_renderUI:function(e){var t=this.getNode(),n=t.get("tagName").toLowerCase();t.addClass(r.CLASS_NAMES.BUTTON),n!=="button"&&n!=="input"&&t.set("role","button")},enable:function(){this.set("disabled",!1)},disable:function(){this.set("disabled",!0)},getNode:function(){return this._host},_getLabel:function(){var e=this.getNode(),t=e.get("tagName").toLowerCase(),n;return t==="input"?n=e.get("value"):n=(e.one("."+r.CLASS_NAMES.LABEL)||e).get("text"),n},_uiSetLabel:function(e){var t=this.getNode(),n=t.get("tagName").toLowerCase();return n==="input"?t.set("value",e):(t.one("."+r.CLASS_NAMES.LABEL)||t).set("text",e),e},_uiSetDisabled:function(e){var t=this.getNode();return t.getDOMNode().disabled=e,t.toggleClass(r.CLASS_NAMES.DISABLED,e),e}},r.ATTRS={label:{setter:"_uiSetLabel",getter:"_getLabel",lazyAdd:!1},disabled:{value:!1,setter:"_uiSetDisabled",lazyAdd:!1}},r.NAME="button",r.CLASS_NAMES={BUTTON:n("button"),DISABLED:n("button","disabled"),SELECTED:n("button","selected"),LABEL:n("button","label")},r.ARIA_STATES={PRESSED:"aria-pressed",CHECKED:"aria-checked"},r.ARIA_ROLES={BUTTON:"button",CHECKBOX:"checkbox",TOGGLE:"toggle"},e.mix(r.prototype,e.AttributeCore.prototype),e.ButtonCore=r},"3.7.3",{requires:["attribute-core","classnamemanager","node-base"]});
diff --git a/js/yui3/button-group/button-group-min.js b/js/yui3/button-group/button-group-min.js
new file mode 100644
index 000000000..e35526443
--- /dev/null
+++ b/js/yui3/button-group/button-group-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("button-group",function(e,t){function s(){s.superclass.constructor.apply(this,arguments)}var n="contentBox",r="click",i=e.ButtonCore.CLASS_NAMES;e.ButtonGroup=e.extend(s,e.Widget,{renderUI:function(){this.getButtons().plug(e.Plugin.Button)},bindUI:function(){var t=this,i=t.get(n);i.delegate(r,t._handleClick,e.ButtonGroup.BUTTON_SELECTOR,t)},getButtons:function(){var t=this.get(n);return t.all(e.ButtonGroup.BUTTON_SELECTOR)},getSelectedButtons:function(){var e=this,t=[],n=e.getButtons(),r=s.CLASS_NAMES.SELECTED;return n.each(function(e){e.hasClass(r)&&t.push(e)}),t},getSelectedValues:function(){var t=this,n,r=[],i=t.getSelectedButtons(),o=s.CLASS_NAMES.SELECTED;return e.Array.each(i,function(e){e.hasClass(o)&&(n=e.getContent(),r.push(n))}),r},_handleClick:function(e){var t=this,n=e.target.ancestor("."+s.CLASS_NAMES.BUTTON,!0),r=t.get("type"),i=s.CLASS_NAMES.SELECTED,o=n.hasClass(i),u;r==="checkbox"?(n.toggleClass(i,!o),t.fire("selectionChange",{originEvent:e})):r==="radio"&&(o||(u=t.getButtons(),u.removeClass(i),n.addClass(i),t.fire("selectionChange",{originEvent:e})))}},{NAME:"buttongroup",ATTRS:{type:{writeOnce:"initOnly",value:"radio"}},CLASS_NAMES:i,BUTTON_SELECTOR:"button, input[type=button], input[type=reset], input[type=submit], input[type=radio], input[type=checkbox]"})},"3.7.3",{requires:["button-plugin","cssbutton","widget"]});
diff --git a/js/yui3/button-plugin/button-plugin-min.js b/js/yui3/button-plugin/button-plugin-min.js
new file mode 100644
index 000000000..1c9c30cd2
--- /dev/null
+++ b/js/yui3/button-plugin/button-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("button-plugin",function(e,t){function n(e){n.superclass.constructor.apply(this,arguments)}e.extend(n,e.ButtonCore,{_afterNodeGet:function(t){var n=this.constructor.ATTRS,r=n[t]&&n[t].getter&&this[n[t].getter];if(r)return new e.Do.AlterReturn("get "+t,r.call(this))},_afterNodeSet:function(e,t){var n=this.constructor.ATTRS,r=n[e]&&n[e].setter&&this[n[e].setter];r&&r.call(this,t)},_initNode:function(t){var n=t.host;this._host=n,e.Do.after(this._afterNodeGet,n,"get",this),e.Do.after(this._afterNodeSet,n,"set",this)},destroy:function(){}},{ATTRS:e.merge(e.ButtonCore.ATTRS),NAME:"buttonPlugin",NS:"button"}),n.createNode=function(t,n){var r;return t&&!n&&!t.nodeType&&!t.getDOMNode&&typeof t!="string"&&(n=t,t=n.srcNode),n=n||{},r=n.template||e.Plugin.Button.prototype.TEMPLATE,t=t||n.srcNode||e.DOM.create(r),e.one(t).plug(e.Plugin.Button,n)},e.namespace("Plugin").Button=n},"3.7.3",{requires:["button-core","cssbutton","node-pluginhost"]});
diff --git a/js/yui3/button/button-min.js b/js/yui3/button/button-min.js
new file mode 100644
index 000000000..a56ec75b3
--- /dev/null
+++ b/js/yui3/button/button-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("button",function(e,t){function s(e){s.superclass.constructor.apply(this,arguments)}function o(e){s.superclass.constructor.apply(this,arguments)}var n=e.ButtonCore.CLASS_NAMES,r=e.ButtonCore.ARIA_STATES,i=e.ButtonCore.ARIA_ROLES;e.extend(s,e.Widget,{BOUNDING_TEMPLATE:e.ButtonCore.prototype.TEMPLATE,CONTENT_TEMPLATE:null,initializer:function(e){this._host=this.get("boundingBox")},bindUI:function(){var e=this;e.after("labelChange",e._afterLabelChange),e.after("disabledChange",e._afterDisabledChange)},syncUI:function(){var e=this;e._uiSetLabel(e.get("label")),e._uiSetDisabled(e.get("disabled"))},_afterLabelChange:function(e){this._uiSetLabel(e.newVal)},_afterDisabledChange:function(e){this._uiSetDisabled(e.newVal)}},{NAME:"button",ATTRS:{label:{value:e.ButtonCore.ATTRS.label.value},disabled:{value:!1}},HTML_PARSER:{label:function(e){return this._host=e,this._getLabel()},disabled:function(e){return e.getDOMNode().disabled}},CLASS_NAMES:n}),e.mix(s.prototype,e.ButtonCore.prototype),e.extend(o,s,{trigger:"click",selectedAttrName:"",initializer:function(e){var t=this,n=t.get("type"),r=n==="checkbox"?"checked":"pressed",i=e[r]||!1;t.addAttr(r,{value:i}),t.selectedAttrName=r},destructor:function(){delete this.selectedAttrName},bindUI:function(){var e=this,t=e.get("contentBox");o.superclass.bindUI.call(e),t.on(e.trigger,e.toggle,e),e.after(e.selectedAttrName+"Change",e._afterSelectedChange)},syncUI:function(){var e=this,t=e.get("contentBox"),n=e.get("type"),r=o.ARIA_ROLES,i=n==="checkbox"?r.CHECKBOX:r.TOGGLE,s=e.selectedAttrName;o.superclass.syncUI.call(e),t.set("role",i),e._uiSetSelected(e.get(s))},_afterSelectedChange:function(e){this._uiSetSelected(e.newVal)},_uiSetSelected:function(e){var t=this,n=t.get("contentBox"),r=o.ARIA_STATES,i=t.get("type"),u=i==="checkbox"?r.CHECKED:r.PRESSED;n.toggleClass(s.CLASS_NAMES.SELECTED,e),n.set(u,e)},toggle:function(){var e=this;e._set(e.selectedAttrName,!e.get(e.selectedAttrName))}},{NAME:"toggleButton",ATTRS:{type:{value:"toggle",writeOnce:"initOnly"}},HTML_PARSER:{checked:function(e){return e.hasClass(n.SELECTED)},pressed:function(e){return e.hasClass(n.SELECTED)}},ARIA_STATES:r,ARIA_ROLES:i,CLASS_NAMES:n}),e.Button=s,e.ToggleButton=o},"3.7.3",{requires:["button-core","cssbutton","widget"]});
diff --git a/js/yui3/cache-base/cache-base-min.js b/js/yui3/cache-base/cache-base-min.js
new file mode 100644
index 000000000..016909447
--- /dev/null
+++ b/js/yui3/cache-base/cache-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("cache-base",function(e,t){var n=e.Lang,r=e.Lang.isDate,i=function(){i.superclass.constructor.apply(this,arguments)};e.mix(i,{NAME:"cache",ATTRS:{max:{value:0,setter:"_setMax"},size:{readOnly:!0,getter:"_getSize"},uniqueKeys:{value:!1},expires:{value:0,validator:function(t){return e.Lang.isDate(t)||e.Lang.isNumber(t)&&t>=0}},entries:{readOnly:!0,getter:"_getEntries"}}}),e.extend(i,e.Base,{_entries:null,initializer:function(e){this.publish("add",{defaultFn:this._defAddFn}),this.publish("flush",{defaultFn:this._defFlushFn}),this._entries=[]},destructor:function(){this._entries=[]},_setMax:function(e){var t=this._entries;if(e>0){if(t)while(t.length>e)t.shift()}else e=0,this._entries=[];return e},_getSize:function(){return this._entries.length},_getEntries:function(){return this._entries},_defAddFn:function(e){var t=this._entries,r=e.entry,i=this.get("max"),s;this.get("uniqueKeys")&&(s=this._position(e.entry.request),n.isValue(s)&&t.splice(s,1));while(i&&t.length>=i)t.shift();t[t.length]=r},_defFlushFn:function(e){var t=this._entries,r=e.details[0],i;r&&n.isValue(r.request)?(i=this._position(r.request),n.isValue(i)&&t.splice(i,1)):this._entries=[]},_isMatch:function(e,t){return!t.expires||new Date<t.expires?e===t.request:!1},_position:function(e){var t=this._entries,n=t.length,r=n-1;if(this.get("max")===null||this.get("max")>0)for(;r>=0;r--)if(this._isMatch(e,t[r]))return r;return null},add:function(e,t){var i=this.get("expires");this.get("initialized")&&(this.get("max")===null||this.get("max")>0)&&(n.isValue(e)||n.isNull(e)||n.isUndefined(e))&&this.fire("add",{entry:{request:e,response:t,cached:new Date,expires:r(i)?i:i?new Date((new Date).getTime()+this.get("expires")):null}})},flush:function(e){this.fire("flush",{request:n.isValue(e)?e:null})},retrieve:function(e){var t=this._entries,r=t.length,i=null,s;if(r>0&&(this.get("max")===null||this.get("max")>0)){this.fire("request",{request:e}),s=this._position(e);if(n.isValue(s))return i=t[s],this.fire("retrieve",{entry:i}),s<r-1&&(t.splice(s,1),t[t.length]=i),i}return null}}),e.Cache=i},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/cache-offline/cache-offline-min.js b/js/yui3/cache-offline/cache-offline-min.js
new file mode 100644
index 000000000..825d91b55
--- /dev/null
+++ b/js/yui3/cache-offline/cache-offline-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("cache-offline",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}var r=null,i=e.JSON;try{r=e.config.win.localStorage}catch(s){}e.mix(n,{NAME:"cacheOffline",ATTRS:{sandbox:{value:"default",writeOnce:"initOnly"},expires:{value:864e5},max:{value:null,readOnly:!0},uniqueKeys:{value:!0,readOnly:!0,setter:function(){return!0}}},flushAll:function(){var e=r,t;if(e)if(e.clear)e.clear();else for(t in e)e.hasOwnProperty(t)&&(e.removeItem(t),delete e[t])}}),e.extend(n,e.Cache,r?{_setMax:function(e){return null},_getSize:function(){var e=0,t=0,n=r.length;for(;t<n;++t)r.key(t).indexOf(this.get("sandbox"))===0&&e++;return e},_getEntries:function(){var e=[],t=0,n=r.length,s=this.get("sandbox");for(;t<n;++t)r.key(t).indexOf(s)===0&&(e[t]=i.parse(r.key(t).substring(s.length)));return e},_defAddFn:function(e){var t=e.entry,n=t.request,s=t.cached,o=t.expires;t.cached=s.getTime(),t.expires=o?o.getTime():o;try{r.setItem(this.get("sandbox")+i.stringify({request:n}),i.stringify(t))}catch(u){this.fire("error",{error:u})}},_defFlushFn:function(e){var t,n=r.length-1;for(;n>-1;--n)t=r.key(n),t.indexOf(this.get("sandbox"))===0&&r.removeItem(t)},retrieve:function(e){this.fire("request",{request:e});var t,n,s;try{s=this.get("sandbox")+i.stringify({request:e});try{t=i.parse(r.getItem(s))}catch(o){}}catch(u){}if(t){t.cached=new Date(t.cached),n=t.expires,n=n?new Date(n):null,t.expires=n;if(this._isMatch(e,t))return this.fire("retrieve",{entry:t}),t}return null}}:{_setMax:function(e){return null}}),e.CacheOffline=n},"3.7.3",{requires:["cache-base","json"]});
diff --git a/js/yui3/cache-plugin/cache-plugin-min.js b/js/yui3/cache-plugin/cache-plugin-min.js
new file mode 100644
index 000000000..20f429b8f
--- /dev/null
+++ b/js/yui3/cache-plugin/cache-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("cache-plugin",function(e,t){function n(t){var n=t&&t.cache?t.cache:e.Cache,r=e.Base.create("dataSourceCache",n,[e.Plugin.Base]),i=new r(t);return r.NS="tmpClass",i}e.mix(n,{NS:"cache",NAME:"cachePlugin"}),e.namespace("Plugin").Cache=n},"3.7.3",{requires:["plugin","cache-base"]});
diff --git a/js/yui3/calendar-base/assets/calendar-base-core.css b/js/yui3/calendar-base/assets/calendar-base-core.css
new file mode 100644
index 000000000..ba141766d
--- /dev/null
+++ b/js/yui3/calendar-base/assets/calendar-base-core.css
@@ -0,0 +1,27 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar {
+}
+
+.yui3-calendar-content {
+}
+
+.yui3-calendar-pane {
+ width: 100%;
+}
+
+.yui3-calendar-grid {
+ width: 100%;
+}
+
+.yui3-calendar-column-hidden, .yui3-calendar-hidden {
+ display:none;
+}
+
+.yui3-calendar-day {
+
+} \ No newline at end of file
diff --git a/js/yui3/calendar-base/assets/skins/night/calendar-base.css b/js/yui3/calendar-base/assets/skins/night/calendar-base.css
new file mode 100644
index 000000000..2779a563d
--- /dev/null
+++ b/js/yui3/calendar-base/assets/skins/night/calendar-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-pane{width:100%}.yui3-calendar-grid{width:100%}.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-skin-night .yui3-calendar-content{padding:10px;color:#cbcbcb;border:1px solid #303030;background:#151515;background:-moz-linear-gradient(top,#222 0,#151515 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#222),color-stop(100%,#151515));background:-webkit-linear-gradient(top,#222 0,#151515 100%);background:-o-linear-gradient(top,#222 0,#151515 100%);background:-ms-linear-gradient(top,#222 0,#151515 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#222222',endColorstr='#151515',GradientType=0);background:linear-gradient(top,#222 0,#151515 100%);-moz-border-radius:5px;border-radius:5px}.yui3-skin-night .yui3-calendar-grid{padding:5px;border-collapse:collapse}.yui3-skin-night .yui3-calendar-header{padding-bottom:10px}.yui3-skin-night .yui3-calendar-header-label{margin:0;font-size:1em;font-weight:bold}.yui3-skin-night .yui3-calendar-day,.yui3-skin-night .yui3-calendar-prevmonth-day,.yui3-skin-night .yui3-calendar-nextmonth-day{padding:5px;border:1px solid #151515;background:#262727;text-align:center}.yui3-skin-night .yui3-calendar-day:hover{background:#383939;color:#fff}.yui3-skin-night .yui3-calendar-selection-disabled,.yui3-skin-night .yui3-calendar-selection-disabled:hover{background:#151515;color:#596060}.yui3-skin-night .yui3-calendar-weekday{color:#4f4f4f;font-weight:bold;text-align:center}.yui3-skin-night .yui3-calendar-prevmonth-day,.yui3-skin-night .yui3-calendar-nextmonth-day{color:#4f4f4f}.yui3-skin-night .yui3-calendar-day{font-weight:bold}.yui3-skin-night .yui3-calendar-day-selected{background-color:#505151;color:#fff}.yui3-skin-night .yui3-calendar-header-label{text-align:center}.yui3-skin-night .yui3-calendar-left-grid{margin-right:1em}.yui3-skin-sam .yui3-calendar-right-grid{margin-left:1em}#yui3-css-stamp.skin-night-calendar-base{display:none}
diff --git a/js/yui3/calendar-base/assets/skins/sam/calendar-base.css b/js/yui3/calendar-base/assets/skins/sam/calendar-base.css
new file mode 100644
index 000000000..e24474df6
--- /dev/null
+++ b/js/yui3/calendar-base/assets/skins/sam/calendar-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-pane{width:100%}.yui3-calendar-grid{width:100%}.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-skin-sam .yui3-calendar-content{padding:10px;color:#000;border:1px solid gray;background:#f2f2f2;background:-moz-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f9f9f9),color-stop(100%,#f2f2f2));background:-webkit-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-o-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);background:-ms-linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9',endColorstr='#f2f2f2',GradientType=0);background:linear-gradient(top,#f9f9f9 0,#f2f2f2 100%);-moz-border-radius:5px;border-radius:5px}.yui3-skin-sam .yui3-calendar-grid{padding:5px;border-collapse:collapse}.yui3-skin-sam .yui3-calendar-header{padding-bottom:10px}.yui3-skin-sam .yui3-calendar-header-label{margin:0;font-size:1em;font-weight:bold}.yui3-skin-sam .yui3-calendar-day,.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{padding:5px;border:1px solid #ccc;background:#fff;text-align:center}.yui3-skin-sam .yui3-calendar-day:hover{background:#06c;color:#fff}.yui3-skin-sam .yui3-calendar-selection-disabled,.yui3-skin-sam .yui3-calendar-selection-disabled:hover{color:#a6a6a6;background:#ccc}.yui3-skin-sam .yui3-calendar-weekday{font-weight:bold}.yui3-skin-sam .yui3-calendar-prevmonth-day,.yui3-skin-sam .yui3-calendar-nextmonth-day{color:#a6a6a6}.yui3-skin-sam .yui3-calendar-day{font-weight:bold}.yui3-skin-sam .yui3-calendar-day-selected{background-color:#b3d4ff;color:#000}.yui3-skin-sam .yui3-calendar-header-label{text-align:center}.yui3-skin-sam .yui3-calendar-left-grid{margin-right:1em}.yui3-skin-sam .yui3-calendar-right-grid{margin-left:1em}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar-base{display:none}
diff --git a/js/yui3/calendar-base/calendar-base-min.js b/js/yui3/calendar-base/calendar-base-min.js
new file mode 100644
index 000000000..e1a0917bc
--- /dev/null
+++ b/js/yui3/calendar-base/calendar-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("calendar-base",function(e,t){function P(e){P.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="calendar",i=n(r,"grid"),s=n(r,"left-grid"),o=n(r,"right-grid"),u=n(r,"body"),a=n(r,"header"),f=n(r,"header-label"),l=n(r,"weekdayrow"),c=n(r,"weekday"),h=n(r,"column-hidden"),p=n(r,"day-selected"),d=n(r,"selection-disabled"),v=n(r,"row"),m=n(r,"day"),g=n(r,"prevmonth-day"),y=n(r,"nextmonth-day"),b=n(r,"anchor"),w=n(r,"pane"),E=n(r,"status"),S=e.Lang,x=e.Node,T=x.create,N=e.substitute,C=e.each,k=e.Array.hasValue,L=e.Array.indexOf,A=e.Object.hasKey,O=e.Object.setValue,M=e.Object.owns,_=e.Object.isEmpty,D=e.DataType.Date;e.CalendarBase=e.extend(P,e.Widget,{_paneProperties:{},_paneNumber:1,_calendarId:null,_selectedDates:{},_rules:{},_filterFunction:null,_storedDateCells:{},initializer:function(){this._paneProperties={},this._calendarId=e.guid("calendar"),this._selectedDates={},_(this._rules)&&(this._rules={}),this._storedDateCells={}},renderUI:function(){var e=this.get("contentBox");e.appendChild(this._initCalendarHTML(this.get("date"))),this.get("showPrevMonth")&&this._afterShowPrevMonthChange(),this.get("showNextMonth")&&this._afterShowNextMonthChange(),this._renderCustomRules(),this._renderSelectedDates(),this.get("boundingBox").setAttribute("aria-labelledby",this._calendarId+"_header")},bindUI:function(){this.after("dateChange",this._afterDateChange),this.after("showPrevMonthChange",this._afterShowPrevMonthChange),this.after("showNextMonthChange",this._afterShowNextMonthChange),this.after("headerRendererChange",this._afterHeaderRendererChange),this.after("customRendererChange",this._afterCustomRendererChange),this.after("enabledDatesRuleChange",this._afterCustomRendererChange),this.after("disabledDatesRuleChange",this._afterCustomRendererChange),this.after("focusedChange",this._afterFocusedChange),this.after("selectionChange",this._renderSelectedDates),this._bindCalendarEvents()},_getSelectedDatesList:function(){var e=[];return C(this._selectedDates,function(t){C(t,function(t){C(t,function(t){e.push(t)},this)},this)},this),e},_getSelectedDatesInMonth:function(t){var n=t.getFullYear(),r=t.getMonth();return A(this._selectedDates,n)&&A(this._selectedDates[n],r)?e.Object.values(this._selectedDates[n][r]):[]},_isNumInList:function(e,t){if(t=="all")return!0;var n=t.split(","),r=n.length;while(r--){var i=n[r].split("-");if(i.length==2&&e>=parseInt(i[0],10)&&e<=parseInt(i[1],10))return!0;if(i.length==1&&parseInt(n[r],10)==e)return!0}return!1},_getRulesForDate:function(e){var t=e.getFullYear(),n=e.getMonth(),r=e.getDate(),i=e.getDay(),s=this._rules,o=[],u,a,f,l;for(u in s)if(this._isNumInList(t,u))if(S.isString(s[u]))o.push(s[u]);else for(a in s[u])if(this._isNumInList(n,a))if(S.isString(s[u][a]))o.push(s[u][a]);else for(f in s[u][a])if(this._isNumInList(r,f))if(S.isString(s[u][a][f]))o.push(s[u][a][f]);else for(l in s[u][a][f])this._isNumInList(i,l)&&S.isString(s[u][a][f][l])&&o.push(s[u][a][f][l]);return o},_matchesRule:function(e,t){return L(this._getRulesForDate(e),t)>=0},_canBeSelected:function(e){var t=this.get("enabledDatesRule"),n=this.get("disabledDatesRule");return t?this._matchesRule(e,t):n?!this._matchesRule(e,n):!0},selectDates:function(e){D.isValidDate(e)?this._addDateToSelection(e):S.isArray(e)&&this._addDatesToSelection(e)},deselectDates:function(e){e?D.isValidDate(e)?this._removeDateFromSelection(e):S.isArray(e)&&this._removeDatesFromSelection(e):this._clearSelection()},_addDateToSelection:function(e,t){if(this._canBeSelected(e)){var n=e.getFullYear(),r=e.getMonth(),i=e.getDate();A(this._selectedDates,n)?A(this._selectedDates[n],r)?this._selectedDates[n][r][i]=e:(this._selectedDates[n][r]={},this._selectedDates[n][r][i]=e):(this._selectedDates[n]={},this._selectedDates[n][r]={},this._selectedDates[n][r][i]=e),this._selectedDates=O(this._selectedDates,[n,r,i],e),t||this._fireSelectionChange()}},_addDatesToSelection:function(e){C(e,this._addDateToSelection,this),this._fireSelectionChange()},_addDateRangeToSelection:function(e,t){var n=(t.getTimezoneOffset()-e.getTimezoneOffset())*6e4,r=e.getTime(),i=t.getTime();if(r>i){var s=r;r=i,i=s+n}else i-=n;for(var o=r;o<=i;o+=864e5){var u=new Date(o);u.setHours(12),this._addDateToSelection(u,o)}this._fireSelectionChange()},_removeDateFromSelection:function(e,t){var n=e.getFullYear(),r=e.getMonth(),i=e.getDate();A(this._selectedDates,n)&&A(this._selectedDates[n],r)&&A(this._selectedDates[n][r],i)&&(delete this._selectedDates[n][r][i],t||this._fireSelectionChange())},_removeDatesFromSelection:function(e){C(e,this._removeDateFromSelection,this),this._fireSelectionChange()},_removeDateRangeFromSelection:function(e,t){var n=e.getTime(),r=t.getTime();for(var i=n;i<=r;i+=864e5)this._removeDateFromSelection(new Date(i),i);this._fireSelectionChange()},_clearSelection:function(e){this._selectedDates={},this.get("contentBox").all("."+p).removeClass(p).setAttribute("aria-selected",!1),e||this._fireSelectionChange()},_fireSelectionChange:function(){this.fire("selectionChange",{newSelection:this._getSelectedDatesList()})},_restoreModifiedCells:function(){var e=this.get("contentBox"),t;for(t in this._storedDateCells)e.one("#"+t).replace(this._storedDateCells[t]),delete this._storedDateCells[t]},_renderCustomRules:function(){this.get("contentBox").all("."+m+",."+y).removeClass(d).setAttribute("aria-disabled",!1);if(!_(this._rules)){var e=this.get("enabledDatesRule"),t=this.get("disabledDatesRule");for(var n=0;n<this._paneNumber;n++){var r=D.addMonths(this.get("date"),n),i=D.listOfDatesInMonth(r);C(i,function(n){var r=this._getRulesForDate(n);if(r.length>0){var i=this._dateToNode(n);(e&&L(r,e)<0||!e&&t&&L(r,t)>=0)&&i.addClass(d).setAttribute("aria-disabled",!0),S.isFunction(this._filterFunction)&&(this._storedDateCells[i.get("id")]=i.cloneNode(!0),this._filterFunction(n,i,r))}else if(e){var i=this._dateToNode(n);i.addClass(d).setAttribute("aria-disabled",!0)}},this)}}},_renderSelectedDates:function(){this.get("contentBox").all("."+p).removeClass(p).setAttribute("aria-selected",!1);for(var e=0;e<this._paneNumber;e++){var t=D.addMonths(this.get("date"),e),n=this._getSelectedDatesInMonth(t);C(n,function(e){this._dateToNode(e).addClass(p).setAttribute("aria-selected",!0)},this)}},_dateToNode:function(e){var t=e.getDate(),n=0,r=t%7,i=(12+e.getMonth()-this.get("date").getMonth())%12,s=this._calendarId+"_pane_"+i,o=this._paneProperties[s].cutoffCol;switch(r){case 0:o>=6?n=12:n=5;break;case 1:n=6;break;case 2:o>0?n=7:n=0;break;case 3:o>1?n=8:n=1;break;case 4:o>2?n=9:n=2;break;case 5:o>3?n=10:n=3;break;case 6:o>4?n=11:n=4}return this.get("contentBox").one("#"+this._calendarId+"_pane_"+i+"_"+n+"_"+t)},_nodeToDate:function(e){var t=e.get("id").split("_").reverse(),n=parseInt(t[2],10),r=parseInt(t[0],10),i=D.addMonths(this.get("date"),n),s=i.getFullYear(),o=i.getMonth();return new Date(s,o,r,12,0,0,0)},_bindCalendarEvents:function(){},_normalizeDate:function(e){return e?new Date(e.getFullYear(),e.getMonth(),1,12,0,0,0):null},_getCutoffColumn:function(e,t){var n=this._normalizeDate(e).getDay()-t,r=6-(n+7)%7;return r},_turnPrevMonthOn:function(e){var t=e.get("id"),n=this._paneProperties[t].paneDate,r=D.daysInMonth(D.addMonths(n,-1));this._paneProperties[t].hasOwnProperty("daysInPrevMonth")||(this._paneProperties[t].daysInPrevMonth=0);if(r!=this._paneProperties[t].daysInPrevMonth){this._paneProperties[t].daysInPrevMonth=r;for(var i=5;i>=0;i--)e.one("#"+t+"_"+i+"_"+(i-5)).set("text",r--)}},_turnPrevMonthOff:function(e){var t=e.get("id");this._paneProperties[t].daysInPrevMonth=0;for(var n=5;n>=0;n--)e.one("#"+t+"_"+n+"_"+(n-5)).setContent("&nbsp;")},_cleanUpNextMonthCells:function(e){var t=e.get("id");e.one("#"+t+"_6_29").removeClass(y),e.one("#"+t+"_7_30").removeClass(y),e.one("#"+t+"_8_31").removeClass(y),e.one("#"+t+"_0_30").removeClass(y),e.one("#"+t+"_1_31").removeClass(y)},_turnNextMonthOn:function(e){var t=1,n=e.get("id"),r=this._paneProperties[n].daysInMonth,i=this._paneProperties[n].cutoffCol;for(var s=r-22;s<i+7;s++)e.one("#"+n+"_"+s+"_"+(s+23)).set("text",t++).addClass(y);var o=i;r==31&&i<=1?o=2:r==30&&i===0&&(o=1);for(var s=o;s<i+7;s++)e.one("#"+n+"_"+s+"_"+(s+30)).set("text",t++).addClass(y)},_turnNextMonthOff:function(e){var t=e.get("id"),n=this._paneProperties[t].daysInMonth,r=this._paneProperties[t].cutoffCol;for(var i=n-22;i<=12;i++)e.one("#"+t+"_"+i+"_"+(i+23)).setContent("&nbsp;").addClass(y);var s=0;n==31&&r<=1?s=2:n==30&&r===0&&(s=1);for(var i=s;i<=12;i++)e.one("#"+t+"_"+i+"_"+(i+30)).setContent("&nbsp;").addClass(y)},_afterShowNextMonthChange:function(){var e=this.get("contentBox"),t=e.one("#"+this._calendarId+"_pane_"+(this._paneNumber-1));this._cleanUpNextMonthCells(t),this.get("showNextMonth")?this._turnNextMonthOn(t):this._turnNextMonthOff(t)},_afterShowPrevMonthChange:function(){var e=this.get("contentBox"),t=e.one("#"+this._calendarId+"_pane_"+0);this.get("showPrevMonth")?this._turnPrevMonthOn(t):this._turnPrevMonthOff(t)},_afterHeaderRendererChange:function(){var e=this.get("contentBox").one("."+f);e.setContent(this._updateCalendarHeader(this.get("date")))},_afterCustomRendererChange:function(){this._restoreModifiedCells(),this._renderCustomRules()},_afterDateChange:function(){var e=this.get("contentBox"),t=e.one("."+a).one("."+f),n=e.all("."+i),r=this.get("date"),s=0;e.setStyle("visibility","hidden"),t.setContent(this._updateCalendarHeader(r)),this._restoreModifiedCells(),n.each(function(e){this._rerenderCalendarPane(D.addMonths(r,s++),e)},this),this._afterShowPrevMonthChange(),this._afterShowNextMonthChange(),this._renderCustomRules(),this._renderSelectedDates(),e.setStyle("visibility","visible")},_initCalendarPane:function(e,t){var n="",r=this.get("strings.very_short_weekdays")||["Su","Mo","Tu","We","Th","Fr","Sa"],i=this.get("strings.weekdays")||["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],s=this.get("strings.first_weekday")||0,o=this._getCutoffColumn(e,s),u=D.daysInMonth(e),a=["","","","","",""],f={};f.weekday_row="";for(var l=s;l<=s+6;l++)f.weekday_row+=N(P.WEEKDAY_TEMPLATE,{weekdayname:r[l%7],full_weekdayname:i[l%7]});f.weekday_row_template=N(P.WEEKDAY_ROW_TEMPLATE,f);for(var c=0;c<=5;c++)for(var p=0;p<=12;p++){var d=7*c-5+p,v=t+"_"+p+"_"+d,b=m;d<1?b=g:d>u&&(b=y);if(d<1||d>u)d="&nbsp;";var w=p>=o&&p<o+7?"":h;a[c]+=N(P.CALDAY_TEMPLATE,{day_content:d,calendar_col_class:"calendar_col"+p,calendar_col_visibility_class:w,calendar_day_class:b,calendar_day_id:v})}f.body_template="",C(a,function(e){f.body_template+=N(P.CALDAY_ROW_TEMPLATE,{calday_row:e})}),f.calendar_pane_id=t,f.calendar_pane_tabindex=this.get("tabIndex"),f.pane_arialabel=D.format(e,{format:"%B %Y"});var E=N(N(P.CALENDAR_GRID_TEMPLATE,f),P.CALENDAR_STRINGS);return this._paneProperties[t]={cutoffCol:o,daysInMonth:u,paneDate:e},E},_rerenderCalendarPane:function(e,t){var n=this.get("strings.first_weekday")||0,r=this._getCutoffColumn(e,n),i=D.daysInMonth(e),s=t.get("id");t.setStyle("visibility","hidden"),t.setAttribute("aria-label",D.format(e,{format:"%B %Y"}));for(var o=0;o<=12;o++){var u=t.all(".calendar_col"+o);u.removeClass(h);if(o<r||o>=r+7)u.addClass(h);else switch(o){case 0:var a=t.one("#"+s+"_0_30");i>=30?(a.set("text","30"),a.removeClass(y).addClass(m)):(a.setContent("&nbsp;"),a.addClass(y).addClass(m));break;case 1:var a=t.one("#"+s+"_1_31");i>=31?(a.set("text","31"),a.removeClass(y).addClass(m)):(a.setContent("&nbsp;"),a.removeClass(m).addClass(y));break;case 6:var a=t.one("#"+s+"_6_29");i>=29?(a.set("text","29"),a.removeClass(y).addClass(m)):(a.setContent("&nbsp;"),a.removeClass(m).addClass(y));break;case 7:var a=t.one("#"+s+"_7_30");i>=30?(a.set("text","30"),a.removeClass(y).addClass(m)):(a.setContent("&nbsp;"),a.removeClass(m).addClass(y));break;case 8:var a=t.one("#"+s+"_8_31");i>=31?(a.set("text","31"),a.removeClass(y).addClass(m)):(a.setContent("&nbsp;"),a.removeClass(m).addClass(y))}}this._paneProperties[s].cutoffCol=r,this._paneProperties[s].daysInMonth=i,this._paneProperties[s].paneDate=e,t.setStyle("visibility","visible")},_updateCalendarHeader:function(t){var n="",r=this.get("headerRenderer");return e.Lang.isString(r)?n=D.format(t,{format:r}):r instanceof Function&&(n=r.call(this,t)),n},_initCalendarHeader:function(e){return N(N(P.HEADER_TEMPLATE,{calheader:this._updateCalendarHeader(e),calendar_id:this._calendarId}),P.CALENDAR_STRINGS)},_initCalendarHTML:function(t){function i(){var e=this._initCalendarPane(D.addMonths(t,r),n.calendar_id+"_pane_"+r);return r++,e}var n={},r=0;n.header_template=this._initCalendarHeader(t),n.calendar_id=this._calendarId,n.body_template=N(N(P.CONTENT_TEMPLATE,n),P.CALENDAR_STRINGS);var s=n.body_template.replace(/\{calendar_grid_template\}/g,e.bind(i,this));return this._paneNumber=r,s}},{CALENDAR_STRINGS:{calendar_grid_class:i,calendar_body_class:u,calendar_hd_class:a,calendar_hd_label_class:f,calendar_weekdayrow_class:l,calendar_weekday_class:c,calendar_row_class:v,calendar_day_class:m,calendar_dayanchor_class:b,calendar_pane_class:w,calendar_right_grid_class:o,calendar_left_grid_class:s,calendar_status_class:E},CONTENT_TEMPLATE:'<div class="yui3-g {calendar_pane_class}" id="{calendar_id}">{header_template}<div class="yui3-u-1">{calendar_grid_template}</div></div>',ONE_PANE_TEMPLATE:'<div class="yui3-g {calendar_pane_class}" id="{calendar_id}">{header_template}<div class="yui3-u-1">{calendar_grid_template}</div></div>',TWO_PANE_TEMPLATE:'<div class="yui3-g {calendar_pane_class}" id="{calendar_id}">{header_template}<div class="yui3-u-1-2"><div class = "{calendar_left_grid_class}">{calendar_grid_template}</div></div><div class="yui3-u-1-2"><div class = "{calendar_right_grid_class}">{calendar_grid_template}</div></div></div>',THREE_PANE_TEMPLATE:'<div class="yui3-g {calendar_pane_class}" id="{calendar_id}">{header_template}<div class="yui3-u-1-3"><div class = "{calendar_left_grid_class}">{calendar_grid_template}</div></div><div class="yui3-u-1-3">{calendar_grid_template}</div><div class="yui3-u-1-3"><div class = "{calendar_right_grid_class}">{calendar_grid_template}</div></div></div>',CALENDAR_GRID_TEMPLATE:'<table class="{calendar_grid_class}" id="{calendar_pane_id}" role="grid" aria-readonly="true" aria-label="{pane_arialabel}" tabindex="{calendar_pane_tabindex}"><thead>{weekday_row_template}</thead><tbody>{body_template}</tbody></table>',HEADER_TEMPLATE:'<div class="yui3-g {calendar_hd_class}"><div class="yui3-u {calendar_hd_label_class}" id="{calendar_id}_header" aria-role="heading">{calheader}</div></div>',WEEKDAY_ROW_TEMPLATE:'<tr class="{calendar_weekdayrow_class}" role="row">{weekday_row}</tr>',CALDAY_ROW_TEMPLATE:'<tr class="{calendar_row_class}" role="row">{calday_row}</tr>',WEEKDAY_TEMPLATE:'<th class="{calendar_weekday_class}" role="columnheader" aria-label="{full_weekdayname}">{weekdayname}</th>',CALDAY_TEMPLATE:'<td class="{calendar_col_class} {calendar_day_class} {calendar_col_visibility_class}" id="{calendar_day_id}" role="gridcell" tabindex="-1">{day_content}</td>',NAME:"calendarBase",ATTRS:{tabIndex:{value:1},date:{value:new Date,setter:function(e){var t=this._normalizeDate(e);return D.areEqual(t,this.get("date"))?this.get("date"):t}},showPrevMonth:{value:!1},showNextMonth:{value:!1},strings:{valueFn:function(){return e.Intl.get("calendar-base")}},headerRenderer:{value:"%B %Y"},enabledDatesRule:{value:null},disabledDatesRule:{value:null},selectedDates:{readOnly:!0,getter:function(e){return this._getSelectedDatesList()}},customRenderer:{lazyAdd:!1,value:{},setter:function(e){this._rules=e.rules,this._filterFunction=e.filterFunction}}}})},"3.7.3",{requires:["widget","substitute","datatype-date","datatype-date-math","cssgrids"],lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],skinnable:!0});
diff --git a/js/yui3/calendar-base/lang/calendar-base.js b/js/yui3/calendar-base/lang/calendar-base.js
new file mode 100644
index 000000000..adaae3dbf
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base",function(e){e.Intl.add("calendar-base","",{weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],short_weekdays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],very_short_weekdays:["Su","Mo","Tu","We","Th","Fr","Sa"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_de.js b/js/yui3/calendar-base/lang/calendar-base_de.js
new file mode 100644
index 000000000..05f0c2048
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_de.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_de",function(e){e.Intl.add("calendar-base","de",{weekdays:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],very_short_weekdays:["So","Mo","Di","Mi","Do","Fr","Sa"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_en.js b/js/yui3/calendar-base/lang/calendar-base_en.js
new file mode 100644
index 000000000..20597c0ec
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_en",function(e){e.Intl.add("calendar-base","en",{weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],short_weekdays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],very_short_weekdays:["Su","Mo","Tu","We","Th","Fr","Sa"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_fr.js b/js/yui3/calendar-base/lang/calendar-base_fr.js
new file mode 100644
index 000000000..468bafaa7
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_fr.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_fr",function(e){e.Intl.add("calendar-base","fr",{weekdays:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],short_weekdays:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],very_short_weekdays:["Di","Lu","Ma","Me","Je","Ve","Sa"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_ja.js b/js/yui3/calendar-base/lang/calendar-base_ja.js
new file mode 100644
index 000000000..1bb8ae174
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_ja.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_ja",function(e){e.Intl.add("calendar-base","ja",{weekdays:["\u65e5\u66dc\u65e5","\u6708\u66dc\u65e5","\u706b\u66dc\u65e5","\u6c34\u66dc\u65e5","\u6728\u66dc\u65e5","\u91d1\u66dc\u65e5","\u571f\u66dc\u65e5"],short_weekdays:["\u65e5\u66dc","\u6708\u66dc","\u706b\u66dc","\u6c34\u66dc","\u6728\u66dc","\u91d1\u66dc","\u571f\u66dc"],very_short_weekdays:["\u65e5","\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_nb-NO.js b/js/yui3/calendar-base/lang/calendar-base_nb-NO.js
new file mode 100644
index 000000000..56a0d0f40
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_nb-NO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_nb-NO",function(e){e.Intl.add("calendar-base","nb-NO",{weekdays:["S\u00f8ndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","L\u00f8rdag"],very_short_weekdays:["S\u00f8","Ma","Ti","On","To","Fr","L\u00f8"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_pt-BR.js b/js/yui3/calendar-base/lang/calendar-base_pt-BR.js
new file mode 100644
index 000000000..b22e9e646
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_pt-BR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_pt-BR",function(e){e.Intl.add("calendar-base","pt-BR",{weekdays:["Domingo","Segunda","Ter\u00e7a","Quarta","Quinta","Sexta","S\u00e1bado"],short_weekdays:["Dom","Seg","Ter","Qua","Qui","Sex","Sab"],very_short_weekdays:["Dom","Seg","Ter","Qua","Qui","Sex","Sab"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_ru.js b/js/yui3/calendar-base/lang/calendar-base_ru.js
new file mode 100644
index 000000000..2beaf4921
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_ru.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_ru",function(e){e.Intl.add("calendar-base","ru",{weekdays:["\u0412\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435","\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a","\u0412\u0442\u043e\u0440\u043d\u0438\u043a","\u0421\u0440\u0435\u0434\u0430","\u0427\u0435\u0442\u0432\u0435\u0440\u0433","\u041f\u044f\u0442\u043d\u0438\u0446\u0430","\u0421\u0443\u0431\u0431\u043e\u0442\u0430"],very_short_weekdays:["\u0412\u0441","\u041f\u043d","\u0412\u0442","\u0421\u0440","\u0427\u0442","\u041f\u0442","\u0421\u0431"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar-base/lang/calendar-base_zh-HANT-TW.js b/js/yui3/calendar-base/lang/calendar-base_zh-HANT-TW.js
new file mode 100644
index 000000000..8c3034bc9
--- /dev/null
+++ b/js/yui3/calendar-base/lang/calendar-base_zh-HANT-TW.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar-base_zh-HANT-TW",function(e){e.Intl.add("calendar-base","zh-HANT-TW",{weekdays:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],short_weekdays:["\u9031\u65e5","\u9031\u4e00","\u9031\u4e8c","\u9031\u4e09","\u9031\u56db","\u9031\u4e94","\u9031\u516d"],very_short_weekdays:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar/assets/calendar-core.css b/js/yui3/calendar/assets/calendar-core.css
new file mode 100644
index 000000000..89b40fda2
--- /dev/null
+++ b/js/yui3/calendar/assets/calendar-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar {
+}
+
+.yui3-calendar-content {
+}
+
+.yui3-calendar-column-hidden, .yui3-calendar-hidden {
+ display:none;
+}
+
+.yui3-calendar-day {
+ cursor: pointer;
+}
+
+.yui3-calendar-selection-disabled {
+ cursor: default;
+}
+
+.yui3-calendar-prevmonth-day {
+ cursor: default;
+}
+
+.yui3-calendar-nextmonth-day {
+ cursor: default;
+}
+
+.yui3-calendar-content:hover .yui3-calendar-day,
+.yui3-calendar-content:hover .yui3-calendar-prevmonth-day,
+.yui3-calendar-content:hover .yui3-calendar-nextmonth-day {
+ -moz-user-select: none;
+} \ No newline at end of file
diff --git a/js/yui3/calendar/assets/skins/night/calendar.css b/js/yui3/calendar/assets/skins/night/calendar.css
new file mode 100644
index 000000000..d7f6ead05
--- /dev/null
+++ b/js/yui3/calendar/assets/skins/night/calendar.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-calendar-day{cursor:pointer}.yui3-calendar-selection-disabled{cursor:default}.yui3-calendar-prevmonth-day{cursor:default}.yui3-calendar-nextmonth-day{cursor:default}.yui3-calendar-content:hover .yui3-calendar-day,.yui3-calendar-content:hover .yui3-calendar-prevmonth-day,.yui3-calendar-content:hover .yui3-calendar-nextmonth-day{-moz-user-select:none}.yui3-skin-night .yui3-calendar-day-highlighted{background-color:#555}.yui3-skin-night .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#777}#yui3-css-stamp.skin-night-calendar{display:none}
diff --git a/js/yui3/calendar/assets/skins/sam/calendar.css b/js/yui3/calendar/assets/skins/sam/calendar.css
new file mode 100644
index 000000000..b85758568
--- /dev/null
+++ b/js/yui3/calendar/assets/skins/sam/calendar.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-column-hidden,.yui3-calendar-hidden{display:none}.yui3-calendar-day{cursor:pointer}.yui3-calendar-selection-disabled{cursor:default}.yui3-calendar-prevmonth-day{cursor:default}.yui3-calendar-nextmonth-day{cursor:default}.yui3-calendar-content:hover .yui3-calendar-day,.yui3-calendar-content:hover .yui3-calendar-prevmonth-day,.yui3-calendar-content:hover .yui3-calendar-nextmonth-day{-moz-user-select:none}.yui3-skin-sam .yui3-calendar-day-highlighted{background-color:#dcdef5}.yui3-skin-sam .yui3-calendar-day-selected.yui3-calendar-day-highlighted{background-color:#758fbb}#yui3-css-stamp.skin-sam-calendar{display:none}
diff --git a/js/yui3/calendar/calendar-min.js b/js/yui3/calendar/calendar-min.js
new file mode 100644
index 000000000..099cee8cf
--- /dev/null
+++ b/js/yui3/calendar/calendar-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("calendar",function(e,t){function E(e){E.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="calendar",i=40,s=38,o=37,u=39,a=13,f=32,l=n(r,"header"),c=n(r,"day-selected"),h=n(r,"day-highlighted"),p=n(r,"day"),d=n(r,"prevmonth-day"),v=n(r,"nextmonth-day"),m=n(r,"grid"),g=e.DataType.Date,y=e.delegate,b=n(r,"pane"),w=e.UA.os;e.Calendar=e.extend(E,e.CalendarBase,{_keyEvents:[],_highlightedDateNode:null,_lastSelectedDate:null,initializer:function(){this.plug(e.Plugin.CalendarNavigator),this._keyEvents=[],this._highlightedDateNode=null,this._lastSelectedDate=null},_bindCalendarEvents:function(){var e=this.get("contentBox"),t=e.one("."+b);t.on("selectstart",this._preventSelectionStart),t.delegate("click",this._clickCalendar,"."+p+", ."+d+", ."+v,this),t.delegate("keydown",this._keydownCalendar,"."+m,this),t.delegate("focus",this._focusCalendarGrid,"."+m,this),t.delegate("focus",this._focusCalendarCell,"."+p,this),t.delegate("blur",this._blurCalendarGrid,"."+m+",."+p,this)},_preventSelectionStart:function(e){e.preventDefault()},_highlightDateNode:function(e){this._unhighlightCurrentDateNode();var t=this._dateToNode(e);t.focus(),t.addClass(h)},_unhighlightCurrentDateNode:function(){var e=this.get("contentBox").all("."+h);e&&e.removeClass(h)},_getGridNumber:function(e){var t=e.get("id").split("_").reverse();return parseInt(t[0],10)},_blurCalendarGrid:function(e){this._unhighlightCurrentDateNode()},_focusCalendarCell:function(e){this._highlightedDateNode=e.target,e.stopPropagation()},_focusCalendarGrid:function(e){this._unhighlightCurrentDateNode(),this._highlightedDateNode=null},_keydownCalendar:function(e){var t=this._getGridNumber(e.target),n=this._highlightedDateNode?this._nodeToDate(this._highlightedDateNode):null,r=e.keyCode,l=0,h="";switch(r){case i:l=7,h="s";break;case s:l=-7,h="n";break;case o:l=-1,h="w";break;case u:l=1,h="e";break;case f:case a:e.preventDefault();if(this._highlightedDateNode){var p=this.get("selectionMode");if(p==="single"&&!this._highlightedDateNode.hasClass(c))this._clearSelection(!0),this._addDateToSelection(n);else if(p==="multiple"||p==="multiple-sticky")this._highlightedDateNode.hasClass(c)?this._removeDateFromSelection(n):this._addDateToSelection(n)}}if(r==i||r==s||r==o||r==u){n||(n=g.addMonths(this.get("date"),t),l=0),e.preventDefault();var d=g.addDays(n,l),v=this.get("date"),m=g.addMonths(this.get("date"),this._paneNumber-1),y=new Date(m);m.setDate(g.daysInMonth(m)),g.isInRange(d,v,m)?this._highlightDateNode(d):g.isGreater(v,d)?g.isGreaterOrEqual(this.get("minimumDate"),v)||(this.set("date",g.addMonths(v,-1)),this._highlightDateNode(d)):g.isGreater(d,m)&&(g.isGreaterOrEqual(y,this.get("maximumDate"))||(this.set("date",g.addMonths(v,1)),this._highlightDateNode(d)))}},_clickCalendar:function(e){var t=e.currentTarget,n=t.hasClass(p)&&!t.hasClass(d)&&!t.hasClass(v),r=t.hasClass(c);switch(this.get("selectionMode")){case"single":n&&(r||(this._clearSelection(!0),this._addDateToSelection(this._nodeToDate(t))));break;case"multiple-sticky":n&&(r?this._removeDateFromSelection(this._nodeToDate(t)):this._addDateToSelection(this._nodeToDate(t)));break;case"multiple":if(n)if(!e.metaKey&&!e.ctrlKey&&!e.shiftKey)this._clearSelection(!0),this._lastSelectedDate=this._nodeToDate(t),this._addDateToSelection(this._lastSelectedDate);else if((w=="macintosh"&&e.metaKey||w!="macintosh"&&e.ctrlKey)&&!e.shiftKey)r?(this._removeDateFromSelection(this._nodeToDate(t)),this._lastSelectedDate=null):(this._lastSelectedDate=this._nodeToDate(t),this._addDateToSelection(this._lastSelectedDate));else if((w=="macintosh"&&e.metaKey||w!="macintosh"&&e.ctrlKey)&&e.shiftKey)if(this._lastSelectedDate){var i=this._nodeToDate(t);this._addDateRangeToSelection(i,this._lastSelectedDate),this._lastSelectedDate=i}else this._lastSelectedDate=this._nodeToDate(t),this._addDateToSelection(this._lastSelectedDate);else if(e.shiftKey)if(this._lastSelectedDate){var i=this._nodeToDate(t);this._clearSelection(!0),this._addDateRangeToSelection(i,this._lastSelectedDate),this._lastSelectedDate=i}else this._clearSelection(!0),this._lastSelectedDate=this._nodeToDate(t),this._addDateToSelection(this._lastSelectedDate)}n?this.fire("dateClick",{cell:t,date:this._nodeToDate(t)}):t.hasClass(d)?this.fire("prevMonthClick"):t.hasClass(v)&&this.fire("nextMonthClick")},subtractMonth:function(e){this.set("date",g.addMonths(this.get("date"),-1)),e&&e.halt()},subtractYear:function(e){this.set("date",g.addYears(this.get("date"),-1)),e&&e.halt()},addMonth:function(e){this.set("date",g.addMonths(this.get("date"),1)),e&&e.halt()},addYear:function(e){this.set("date",g.addYears(this.get("date"),1)),e&&e.halt()}},{NAME:"calendar",ATTRS:{selectionMode:{value:"single"},date:{value:new Date,lazyAdd:!1,setter:function(e){var t=this._normalizeDate(e),n=g.addMonths(t,this._paneNumber-1),r=this.get("minimumDate"),i=this.get("maximumDate");if((!r||g.isGreaterOrEqual(t,r))&&(!i||g.isGreaterOrEqual(i,n)))return t;if(r&&g.isGreater(r,t))return r;if(i&&g.isGreater(n,i)){var s=g.addMonths(i,-1*(this._paneNumber-1));return s}}},minimumDate:{value:null,setter:function(e){if(e){var t=this.get("date"),n=this._normalizeDate(e);return t&&!g.isGreaterOrEqual(t,n)&&this.set("date",n),n}return this._normalizeDate(e)}},maximumDate:{value:null,setter:function(e){if(e){var t=this.get("date"),n=this._normalizeDate(e);return t&&!g.isGreaterOrEqual(e,g.addMonths(t,this._paneNumber-1))&&this.set("date",g.addMonths(n,-1*(this._paneNumber-1))),n}return e}}}})},"3.7.3",{requires:["calendar-base","calendarnavigator"],lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],skinnable:!0});
diff --git a/js/yui3/calendar/lang/calendar.js b/js/yui3/calendar/lang/calendar.js
new file mode 100644
index 000000000..d24791cc6
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar",function(e){e.Intl.add("calendar","",{weekdays:["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],short_weekdays:["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],very_short_weekdays:["Mo","Tu","We","Th","Fr","Sa","Su"]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_de.js b/js/yui3/calendar/lang/calendar_de.js
new file mode 100644
index 000000000..c2f74401d
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_de.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_de",function(e){e.Intl.add("calendar","de",{weekdays:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],very_short_weekdays:["So","Mo","Di","Mi","Do","Fr","Sa"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_en.js b/js/yui3/calendar/lang/calendar_en.js
new file mode 100644
index 000000000..914d4f749
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_en",function(e){e.Intl.add("calendar","en",{weekdays:["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],short_weekdays:["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],very_short_weekdays:["Mo","Tu","We","Th","Fr","Sa","Su"]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_fr.js b/js/yui3/calendar/lang/calendar_fr.js
new file mode 100644
index 000000000..81050ae81
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_fr.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_fr",function(e){e.Intl.add("calendar","fr",{weekdays:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],short_weekdays:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],very_short_weekdays:["Di","Lu","Ma","Me","Je","Ve","Sa"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_ja.js b/js/yui3/calendar/lang/calendar_ja.js
new file mode 100644
index 000000000..c52d38fc6
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_ja.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_ja",function(e){e.Intl.add("calendar","ja",{weekdays:["\u6708\u66dc\u65e5","\u706b\u66dc\u65e5","\u6c34\u66dc\u65e5","\u6728\u66dc\u65e5","\u91d1\u66dc\u65e5","\u571f\u66dc\u65e5","\u65e5\u66dc\u65e5"],short_weekdays:["\u6708\u66dc","\u706b\u66dc","\u6c34\u66dc","\u6728\u66dc","\u91d1\u66dc","\u571f\u66dc","\u65e5\u66dc"],very_short_weekdays:["\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f","\u65e5"]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_nb-NO.js b/js/yui3/calendar/lang/calendar_nb-NO.js
new file mode 100644
index 000000000..5e000c789
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_nb-NO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_nb-NO",function(e){e.Intl.add("calendar","nb-NO",{weekdays:["S\u00f8ndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","L\u00f8rdag"],very_short_weekdays:["S\u00f8","Ma","Ti","On","To","Fr","L\u00f8"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_pt-BR.js b/js/yui3/calendar/lang/calendar_pt-BR.js
new file mode 100644
index 000000000..296cb32ac
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_pt-BR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_pt-BR",function(e){e.Intl.add("calendar","pt-BR",{weekdays:["Domingo","Segunda","Ter\u00e7a","Quarta","Quinta","Sexta","S\u00e1bado"],short_weekdays:["Dom","Seg","Ter","Qua","Qui","Sex","Sab"],very_short_weekdays:["Dom","Seg","Ter","Qua","Qui","Sex","Sab"]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_ru.js b/js/yui3/calendar/lang/calendar_ru.js
new file mode 100644
index 000000000..2ca9acce3
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_ru.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_ru",function(e){e.Intl.add("calendar","ru",{weekdays:["\u0412\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435","\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a","\u0412\u0442\u043e\u0440\u043d\u0438\u043a","\u0421\u0440\u0435\u0434\u0430","\u0427\u0435\u0442\u0432\u0435\u0440\u0433","\u041f\u044f\u0442\u043d\u0438\u0446\u0430","\u0421\u0443\u0431\u0431\u043e\u0442\u0430"],very_short_weekdays:["\u0412\u0441","\u041f\u043d","\u0412\u0442","\u0421\u0440","\u0427\u0442","\u041f\u0442","\u0421\u0431"],first_weekday:1,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendar/lang/calendar_zh-HANT-TW.js b/js/yui3/calendar/lang/calendar_zh-HANT-TW.js
new file mode 100644
index 000000000..09a558048
--- /dev/null
+++ b/js/yui3/calendar/lang/calendar_zh-HANT-TW.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/calendar_zh-HANT-TW",function(e){e.Intl.add("calendar","zh-HANT-TW",{weekdays:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],short_weekdays:["\u9031\u65e5","\u9031\u4e00","\u9031\u4e8c","\u9031\u4e09","\u9031\u56db","\u9031\u4e94","\u9031\u516d"],very_short_weekdays:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d"],first_weekday:0,weekends:[0,6]})},"3.7.3");
diff --git a/js/yui3/calendarnavigator/assets/calendarnavigator-core.css b/js/yui3/calendarnavigator/assets/calendarnavigator-core.css
new file mode 100644
index 000000000..ff156f1e4
--- /dev/null
+++ b/js/yui3/calendarnavigator/assets/calendarnavigator-core.css
@@ -0,0 +1,22 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-header {
+ padding-left:15px;
+ padding-right:15px;
+}
+
+.yui3-calendar-header-label {
+ width:100%;
+}
+
+.yui3-calendarnav-prevmonth {
+ cursor: pointer;
+}
+
+.yui3-calendarnav-nextmonth {
+ cursor: pointer;
+} \ No newline at end of file
diff --git a/js/yui3/calendarnavigator/assets/skins/night/calendarnavigator.css b/js/yui3/calendarnavigator/assets/skins/night/calendarnavigator.css
new file mode 100644
index 000000000..4b313142a
--- /dev/null
+++ b/js/yui3/calendarnavigator/assets/skins/night/calendarnavigator.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-header{padding-left:15px;padding-right:15px}.yui3-calendar-header-label{width:100%}.yui3-calendarnav-prevmonth{cursor:pointer}.yui3-calendarnav-nextmonth{cursor:pointer}.yui3-skin-night .yui3-calendarnav-prevmonth,.yui3-skin-night .yui3-calendarnav-nextmonth{color:#fff;width:12px;height:14px;background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALZJREFUeNpi/P//PwORQBqIu6DsMiB+SpQukAUEMCcQVwPx5/8I8BkqxklIPyHDA4H44X/c4CFUDckWGADxgf/EgwNQPQQtEALiaf/JB9OgZmBYwAzERUD84T/l4APULGaYBR5AfPU/9QHITA8maGJiY6A+YENOpmw0CCI2bJEsCsRzKDB8DtSMgUum6DiKiIwWRUlOhhUVdUD8Dcngb1AxgkUFIwmFnRwQt0PZlUD8iBhNAAEGALbfq7SGiQoPAAAAAElFTkSuQmCC);background-repeat:no-repeat}.yui3-skin-night .yui3-calendarnav-prevmonth:hover,.yui3-skin-night .yui3-calendarnav-nextmonth:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPpJREFUeNpi/P//PwMxQD9jszSQ6oJyyy7O8H1KjD5GQhYADeYEUkVAXAHEPFDhL0DcAcR9QIu+k20B0PBAIDUBiOVwKHkExAVAS9aTZAHQYAOowfYMxIGDUIsu4LUAaLAQkGoB4kwG8sB0IK4BWvQOxQKgwcxAdj4Q1wExPwNl4CMQNwHxRKBFfxn10jd5ADm9QKzFQF1wDYiLmaAcNgbqA7CZTEBv7ADS2iDboN5joEIQgczSBpmNHsmiQKodiJPJNHwuEFcCDX49MMkUi0VRUB/hy2ggFy+jtKgohRYVnFDh79CiopuiogLNIjmobxigrn5EjD6AAAMAok9vhfHG8wQAAAAASUVORK5CYII=);color:#06c}.yui3-skin-night .yui3-calendarnav-month-disabled,.yui3-skin-night .yui3-calendarnav-month-disabled:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQhJREFUeNqs0yGLAlEUhuHrKoIgCFbBJghb3F+g0WrVarEqLIhBEEFYWKNNMBktU4z6C5RNkwyCyWQSTPuOfCOCrHNnxwMPyOGe73DAiTmOYywrhy/9/sTBZujN4k0KPbioi6teKuqCmsKGSN/10+q5ehN6QQkrLJB/Mp/Xm5VmAhdkMcEGZWNfZc1MlPGwII42dmiZ/1dLGW1lXhdU8YNvZEz0yijLy6z6FyTN6yvpX7DEOzo4vSD4pCwvc+lfcMEYBUwjhE+VMVbmw7/oiCY+sA4RvNZMUxmB38EWFTSwfxK815uKZkJ/yXMU0cf5rn9Wr6g3f1bC4nwvbIAZRup1Ay671a8AAwC3OzOqxK+rkwAAAABJRU5ErkJggg==);cursor:default;color:#ccc}.yui3-skin-night .yui3-calendarnav-prevmonth,.yui3-skin-night .yui3-calendarnav-prevmonth:hover{background-position:0 0;margin-left:-12px}.yui3-skin-night .yui3-calendarnav-nextmonth,.yui3-skin-night .yui3-calendarnav-nextmonth:hover{background-position:-12px 0;margin-right:-12px}.yui3-skin-night .yui3-calendarnav-prevmonth span,.yui3-skin-night .yui3-calendarnav-nextmonth span{display:none;*display:block}#yui3-css-stamp.skin-night-calendarnavigator{display:none}
diff --git a/js/yui3/calendarnavigator/assets/skins/sam/calendarnavigator.css b/js/yui3/calendarnavigator/assets/skins/sam/calendarnavigator.css
new file mode 100644
index 000000000..0c1039113
--- /dev/null
+++ b/js/yui3/calendarnavigator/assets/skins/sam/calendarnavigator.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-calendar-header{padding-left:15px;padding-right:15px}.yui3-calendar-header-label{width:100%}.yui3-calendarnav-prevmonth{cursor:pointer}.yui3-calendarnav-nextmonth{cursor:pointer}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth{color:#000;width:12px;height:14px;background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKNJREFUeNpiYCAeSAPxUiiWZqAi4ATiaiD+DMT/ofgzVIyTUsMDgfghksHo+CFUDcnAAIgP4DEYHR+A6iEIhIB4GgkGo+NpUDMwADMQFwHxBwoMh+EPULOYYYZ7APFVKhiMjkFmejBBLWFjoD5gQ+dQO4iwOloUiOdQYPgcqBkDl0zRQRQRGS2KGkVFHRB/QzL4G1SMk5qpQg6psJMjVhNAgAEAH+qPqeiPEUsAAAAASUVORK5CYII=);background-repeat:no-repeat}.yui3-skin-sam .yui3-calendarnav-prevmonth:hover,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPpJREFUeNpi/P//PwMxQD9jszSQ6oJyyy7O8H1KjD5GQhYADeYEUkVAXAHEPFDhL0DcAcR9QIu+k20B0PBAIDUBiOVwKHkExAVAS9aTZAHQYAOowfYMxIGDUIsu4LUAaLAQkGoB4kwG8sB0IK4BWvQOxQKgwcxAdj4Q1wExPwNl4CMQNwHxRKBFfxn10jd5ADm9QKzFQF1wDYiLmaAcNgbqA7CZTEBv7ADS2iDboN5joEIQgczSBpmNHsmiQKodiJPJNHwuEFcCDX49MMkUi0VRUB/hy2ggFy+jtKgohRYVnFDh79CiopuiogLNIjmobxigrn5EjD6AAAMAok9vhfHG8wQAAAAASUVORK5CYII=);color:#06c}.yui3-skin-sam .yui3-calendarnav-month-disabled,.yui3-skin-sam .yui3-calendarnav-month-disabled:hover{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAOCAYAAAA1+Nx+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQhJREFUeNqs0yGLAlEUhuHrKoIgCFbBJghb3F+g0WrVarEqLIhBEEFYWKNNMBktU4z6C5RNkwyCyWQSTPuOfCOCrHNnxwMPyOGe73DAiTmOYywrhy/9/sTBZujN4k0KPbioi6teKuqCmsKGSN/10+q5ehN6QQkrLJB/Mp/Xm5VmAhdkMcEGZWNfZc1MlPGwII42dmiZ/1dLGW1lXhdU8YNvZEz0yijLy6z6FyTN6yvpX7DEOzo4vSD4pCwvc+lfcMEYBUwjhE+VMVbmw7/oiCY+sA4RvNZMUxmB38EWFTSwfxK815uKZkJ/yXMU0cf5rn9Wr6g3f1bC4nwvbIAZRup1Ay671a8AAwC3OzOqxK+rkwAAAABJRU5ErkJggg==);cursor:default;color:#ccc}.yui3-skin-sam .yui3-calendarnav-prevmonth,.yui3-skin-sam .yui3-calendarnav-prevmonth:hover{background-position:0 0;margin-left:-12px}.yui3-skin-sam .yui3-calendarnav-nextmonth,.yui3-skin-sam .yui3-calendarnav-nextmonth:hover{background-position:-12px 0;margin-right:-12px}.yui3-skin-sam .yui3-calendarnav-prevmonth span,.yui3-skin-sam .yui3-calendarnav-nextmonth span{display:none;*display:block}#yui3-css-stamp.skin-sam-calendarnavigator{display:none}
diff --git a/js/yui3/calendarnavigator/calendarnavigator-min.js b/js/yui3/calendarnavigator/calendarnavigator-min.js
new file mode 100644
index 000000000..0373c3f20
--- /dev/null
+++ b/js/yui3/calendarnavigator/calendarnavigator-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("calendarnavigator",function(e,t){function m(e){m.superclass.constructor.apply(this,arguments)}var n="contentBox",r="host",i="rendered",s=e.ClassNameManager.getClassName,o=e.substitute,u=e.Node,a=u.create,f="calendar",l="calendarnav",c=s(f,"header"),h=s(l,"prevmonth"),p=s(l,"nextmonth"),d=s(l,"month-disabled"),v=e.DataType.Date;m.NS="navigator",m.NAME="pluginCalendarNavigator",m.ATTRS={shiftByMonths:{value:1}},m.CALENDARNAV_STRINGS={prev_month_class:h,next_month_class:p},m.PREV_MONTH_CONTROL_TEMPLATE='<a class="yui3-u {prev_month_class}" role="button" aria-label="{prev_month_arialabel}" tabindex="{control_tabindex}"><span>&lt;</span></a>',m.NEXT_MONTH_CONTROL_TEMPLATE='<a class="yui3-u {next_month_class}" role="button" aria-label="{next_month_arialabel}" tabindex="{control_tabindex}"><span>&gt;</span></a>',e.extend(m,e.Plugin.Base,{_eventAttachments:{},_controls:{},initializer:function(e){this._controls={},this._eventAttachments={},this.afterHostMethod("renderUI",this._initNavigationControls)},destructor:function(){},_focusNavigation:function(e){e.currentTarget.focus()},_subtractMonths:function(e){if(e.type==="click"||e.type==="keydown"&&(e.keyCode==13||e.keyCode==32)){var t=this.get(r),n=t.get("date");t.set("date",v.addMonths(n,-1*this.get("shiftByMonths"))),e.preventDefault()}},_addMonths:function(e){if(e.type==="click"||e.type==="keydown"&&(e.keyCode==13||e.keyCode==32)){var t=this.get(r),n=t.get("date");t.set("date",v.addMonths(n,this.get("shiftByMonths"))),e.preventDefault()}},_updateControlState:function(){var e=this.get(r);v.areEqual(e.get("minimumDate"),e.get("date"))?(this._eventAttachments.prevMonth&&(this._eventAttachments.prevMonth.detach(),this._eventAttachments.prevMonth=!1),this._controls.prevMonth.hasClass(d)||this._controls.prevMonth.addClass(d).setAttribute("aria-disabled","true")):(this._eventAttachments.prevMonth||(this._eventAttachments.prevMonth=this._controls.prevMonth.on(["click","keydown"],this._subtractMonths,this)),this._controls.prevMonth.hasClass(d)&&this._controls.prevMonth.removeClass(d).setAttribute("aria-disabled","false")),v.areEqual(e.get("maximumDate"),v.addMonths(e.get("date"),e._paneNumber-1))?(this._eventAttachments.nextMonth&&(this._eventAttachments.nextMonth.detach(),this._eventAttachments.nextMonth=!1),this._controls.nextMonth.hasClass(d)||this._controls.nextMonth.addClass(d).setAttribute("aria-disabled","true")):(this._eventAttachments.nextMonth||(this._eventAttachments.nextMonth=this._controls.nextMonth.on(["click","keydown"],this._addMonths,this)),this._controls.nextMonth.hasClass(d)&&this._controls.nextMonth.removeClass(d).setAttribute("aria-disabled","false")),this._controls.prevMonth.on(["click","keydown"],this._focusNavigation,this),this._controls.nextMonth.on(["click","keydown"],this._focusNavigation,this)},_renderPrevControls:function(){var e=a(o(m.PREV_MONTH_CONTROL_TEMPLATE,m.CALENDARNAV_STRINGS));return e.on("selectstart",this.get(r)._preventSelectionStart),e},_renderNextControls:function(){var e=a(o(m.NEXT_MONTH_CONTROL_TEMPLATE,m.CALENDARNAV_STRINGS));return e.on("selectstart",this.get(r)._preventSelectionStart),e},_initNavigationControls:function(){var e=this.get(r);m.CALENDARNAV_STRINGS.control_tabindex=e.get("tabIndex"),m.CALENDARNAV_STRINGS.prev_month_arialabel="Go to previous month",m.CALENDARNAV_STRINGS.next_month_arialabel="Go to next month";var t=e.get(n).one("."+c);this._controls.prevMonth=this._renderPrevControls(),this._controls.nextMonth=this._renderNextControls(),this._updateControlState(),e.after("dateChange",this._updateControlState,this),t.prepend(this._controls.prevMonth),t.append(this._controls.nextMonth)}}),e.namespace("Plugin").CalendarNavigator=m},"3.7.3",{requires:["plugin","classnamemanager","datatype-date","node","substitute"],skinnable:!0});
diff --git a/js/yui3/charts-base/charts-base-min.js b/js/yui3/charts-base/charts-base-min.js
new file mode 100644
index 000000000..1e3280937
--- /dev/null
+++ b/js/yui3/charts-base/charts-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("charts-base",function(e,t){function b(){}function w(e){w.superclass.constructor.apply(this,arguments)}function E(e){E.superclass.constructor.apply(this,arguments)}function S(e){S.superclass.constructor.apply(this,arguments)}function x(e){x.superclass.constructor.apply(this,arguments)}function T(){}function N(){}function C(){}function k(t){var n={area:{getter:function(){return this._defaults||this._getAreaDefaults()},setter:function(t){var n=this._defaults||this._getAreaDefaults();this._defaults=e.merge(n,t)}}};this.addAttrs(n,t),this.get("styles")}function L(e){var t={markers:{getter:function(){return this._markers}}};this.addAttrs(t,e)}function A(){}function O(){}var n=e.config,r=n.win,i=n.doc,s=e.Lang,o=s.isString,u=e.DOM,a,f,l,c,h=e.ClassNameManager.getClassName,p=h("seriesmarker"),d,v,m,g,y;d=function(e){d.superclass.constructor.apply(this,arguments)},d.NAME="shapeGroup",e.extend(d,e.Path,{_draw:function(){var e=this.get("xvalues"),t=this.get("yvalues"),n,r,i,o,u=0,a,f=[],l=this.get("dimensions"),c=l.width,h=l.height,p=l.radius,d=l.yRadius,v=this.get("id"),m=this.node.className,g=s.isArray(c),y=s.isArray(h),b=s.isArray(p),w=s.isArray(d);if(e&&t&&e.length>0){this.clear(),a=e.length;for(;u<a;++u)n=e[u],r=t[u],i=b?p[u]:p,o=w?d[u]:d,!isNaN(n)&&!isNaN(r)&&!isNaN(i)&&(this.drawShape({x:n,y:r,width:g?c[u]:c,height:y?h[u]:h,radius:i,yRadius:o}),this.closePath(),f[u]={id:v+"_"+u,className:m,coords:n-this._left+", "+(r-this._top)+", "+p,shape:"circle"});this._closePath()}},_getRadiusCollection:function(e){var t=0,n=e.length,r=[];for(;t<n;++t)r[t]=e[t]*.5;return r}}),d.ATTRS=e.merge(e.Path.ATTRS,{dimensions:{getter:function(){var e=this._dimensions,t,n,r,i;return e.hasOwnProperty("radius")?e:(r=e.width,i=e.height,t=s.isArray(r)?this._getRadiusCollection(r):r*.5,n=s.isArray(i)?this._getRadiusCollection(i):i*.5,{width:r,height:i,radius:t,yRadius:n})},setter:function(e){return this._dimensions=e,e}},xvalues:{getter:function(){return this._xvalues},setter:function(e){this._xvalues=e}},yvalues:{getter:function(){return this._yvalues},setter:function(e){this._yvalues=e}}}),e.ShapeGroup=d,v=function(e){v.superclass.constructor.apply(this,arguments)},v.NAME="circleGroup",e.extend(v,e.ShapeGroup,{drawShape:function(e){this.drawCircle(e.x,e.y,e.radius)}}),v.ATTRS=e.merge(e.ShapeGroup.ATTRS,{dimensions:{getter:function(){var e=this._dimensions,t,n,r,i;return e.hasOwnProperty("radius")?e:(r=e.width,i=e.height,t=s.isArray(r)?this._getRadiusCollection(r):r*.5,n=t,{width:r,height:i,radius:t,yRadius:n})}}}),v.ATTRS=e.ShapeGroup.ATTRS,e.CircleGroup=v,m=function(e){m.superclass.constructor.apply(this,arguments)},m.NAME="rectGroup",e.extend(m,e.ShapeGroup,{drawShape:function(e){this.drawRect(e.x,e.y,e.width,e.height)}}),m.ATTRS=e.ShapeGroup.ATTRS,e.RectGroup=m,y=function(e){y.superclass.constructor.apply(this,arguments)},y.NAME="diamondGroup",e.extend(y,e.ShapeGroup,{drawShape:function(e){this.drawDiamond(e.x,e.y,e.width,e.height)}}),y.ATTRS=e.ShapeGroup.ATTRS,e.DiamondGroup=y,g=function(e){g.superclass.constructor.apply(this,arguments)},g.NAME="diamondGroup",e.extend(g,e.ShapeGroup,{drawShape:function(e){this.drawEllipse(e.x,e.y,e.width,e.height)}}),g.ATTRS=e.ShapeGroup.ATTRS,e.EllipseGroup=g,b.ATTRS={styles:{getter:function(){return this._styles=this._styles||this._getDefaultStyles(),this._styles},setter:function(e){this._styles=this._setStyles(e)}},graphic:{}},b.NAME="renderer",b.prototype={_styles:null,_setStyles:function(e){var t=this.get("styles");return this._mergeStyles(e,t)},_mergeStyles:function(t,n){n||(n={});var r=e.merge(n,{});return e.Object.each(t,function(e,t,i){n.hasOwnProperty(t)&&s.isObject(e)&&!s.isFunction(e)&&!s.isArray(e)?r[t]=this._mergeStyles(e,n[t]):r[t]=e},this),r},_getDefaultStyles:function(){return{padding:{top:0,right:0,bottom:0,left:0}}}},e.augment(b,e.Attribute),e.Renderer=b,a=function(){},a.prototype={_getDefaultMargins:function(){return{top:0,left:0,right:4,bottom:0}},setTickOffsets:function(){var e=this,t=e.get("styles").majorTicks,n=t.length,r=n*.5,i=t.display;e.set("topTickOffset",0),e.set("bottomTickOffset",0);switch(i){case"inside":e.set("rightTickOffset",n),e.set("leftTickOffset",0);break;case"outside":e.set("rightTickOffset",0),e.set("leftTickOffset",n);break;case"cross":e.set("rightTickOffset",r),e.set("leftTickOffset",r);break;default:e.set("rightTickOffset",0),e.set("leftTickOffset",0)}},drawTick:function(e,t,n){var r=this,i=r.get("styles"),s=i.padding,o=n.length,u={x:s.left,y:t.y},a={x:o+s.left,y:t.y};r.drawLine(e,u,a)},getLineStart:function(){var e=this.get("styles"),t=e.padding,n=e.majorTicks,r=n.length,i=n.display,s={x:t.left,y:0};return i==="outside"?s.x+=r:i==="cross"&&(s.x+=r/2),s},getLabelPoint:function(e){return{x:e.x-this.get("leftTickOffset"),y:e.y}},updateMaxLabelSize:function(e,t){var n=this,r=this._labelRotationProps,i=r.rot,s=r.absRot,o=r.sinRadians,u=r.cosRadians,a;i===0?a=e:s===90?a=t:a=u*e+o*t,n._maxLabelSize=Math.max(n._maxLabelSize,a)},getExplicitlySized:function(e){if(this._explicitWidth){var t=this,n=t._explicitWidth,r=t._totalTitleSize,i=t.get("leftTickOffset"),s=e.label.margin.right;return t._maxLabelSize=n-(i+s+r),!0}return!1},positionTitle:function(e){var t=this,n=t._titleBounds,r=t.get("styles").title.margin,i=t._titleRotationProps,s=n.right-n.left,o=e.offsetWidth,u=e.offsetHeight,a=o*-0.5+s*.5,f=t.get("height")*.5-u*.5;i.labelWidth=o,i.labelHeight=u,r&&r.left&&(a+=r.left),i.x=a,i.y=f,i.transformOrigin=[.5,.5],t._rotate(e,i)},positionLabel:function(e,t,n,r){var i=this,s=i.get("leftTickOffset"),o=this._totalTitleSize,u=t.x+o-s,a=t.y,f=this._labelRotationProps,l=f.rot,c=f.absRot,h=i._maxLabelSize,p=this._labelWidths[r],d=this._labelHeights[r];l===0?(u-=p,a-=d*.5):l===90?u-=p*.5:l===-90?(u-=p*.5,a-=d):(u-=p+d*c/360,a-=d*.5),f.labelWidth=p,f.labelHeight=d,f.x=Math.round(h+u),f.y=Math.round(a),this._rotate(e,f)},_setRotationCoords:function(e){var t=e.rot,n=e.absRot,r,i,s=e.labelWidth,o=e.labelHeight;t===0?(r=s,i=o*.5):t===90?(i=0,r=s*.5):t===-90?(r=s*.5,i=o):(r=s+o*n/360,i=o*.5),e.x-=r,e.y-=i},_getTransformOrigin:function(e){var t;return e===0?t=[0,0]:e===90?t=[.5,0]:e===-90?t=[.5,1]:t=[1,.5],t},offsetNodeForTick:function(e){},setCalculatedSize:function(){var e=this,t=this.get("graphic"),n=e.get("styles"),r=n.label,i=e.get("leftTickOffset"),s=e._maxLabelSize,o=this._totalTitleSize,u=Math.round(o+i+s+r.margin.right);this._explicitWidth&&(u=this._explicitWidth),this.set("calculatedWidth",u),t.set("x",u-i)}},e.LeftAxisLayout=a,f=function(){},f.prototype={_getDefaultMargins:function(){return{top:0,left:4,right:0,bottom:0}},setTickOffsets:function(){var e=this,t=e.get("styles").majorTicks,n=t.length,r=n*.5,i=t.display;e.set("topTickOffset",0),e.set("bottomTickOffset",0);switch(i){case"inside":e.set("leftTickOffset",n),e.set("rightTickOffset",0);break;case"outside":e.set("leftTickOffset",0),e.set("rightTickOffset",n);break;case"cross":e.set("rightTickOffset",r),e.set("leftTickOffset",r);break;default:e.set("leftTickOffset",0),e.set("rightTickOffset",0)}},drawTick:function(e,t,n){var r=this,i=r.get("styles"),s=i.padding,o=n.length,u={x:s.left,y:t.y},a={x:s.left+o,y:t.y};r.drawLine(e,u,a)},getLineStart:function(){var e=this,t=e.get("styles"),n=t.padding,r=t.majorTicks,i=r.length,s=r.display,o={x:n.left,y:n.top};return s==="inside"?o.x+=i:s==="cross"&&(o.x+=i/2),o},getLabelPoint:function(e){return{x:e.x+this.get("rightTickOffset"),y:e.y}},updateMaxLabelSize:function(e,t){var n=this,r=this._labelRotationProps,i=r.rot,s=r.absRot,o=r.sinRadians,u=r.cosRadians,a;i===0?a=e:s===90?a=t:a=u*e+o*t,n._maxLabelSize=Math.max(n._maxLabelSize,a)},getExplicitlySized:function(e){if(this._explicitWidth){var t=this,n=t._explicitWidth,r=this._totalTitleSize,i=t.get("rightTickOffset"),s=e.label.margin.right;return t._maxLabelSize=n-(i+s+r),!0}return!1},positionTitle:function(e){var t=this,n=t._titleBounds,r=t.get("styles").title.margin,i=t._titleRotationProps,s=e.offsetWidth,o=e.offsetHeight,u=n.right-n.left,a=this.get("width")-s*.5-u*.5,f=t.get("height")*.5-o*.5;i.labelWidth=s,i.labelHeight=o,r&&r.right&&(a-=r.left),i.x=a,i.y=f,i.transformOrigin=[.5,.5],t._rotate(e,i)},positionLabel:function(e,t,n,r){var i=this,s=i.get("rightTickOffset"),o=n.label,u=0,a=t.x,f=t.y,l=this._labelRotationProps,c=l.rot,h=l.absRot,p=this._labelWidths[r],d=this._labelHeights[r];o.margin&&o.margin.left&&(u=o.margin.left),c===0?f-=d*.5:c===90?(a-=p*.5,f-=d):c===-90?a-=p*.5:(f-=d*.5,a+=d/2*h/90),a+=u,a+=s,l.labelWidth=p,l.labelHeight=d,l.x=Math.round(a),l.y=Math.round(f),this._rotate(e,l)},_setRotationCoords:function(e){var t=e.rot,n=e.absRot,r=0,i=0,s=e.labelWidth,o=e.labelHeight;t===0?i=o*.5:t===90?(r=s*.5,i=o):t===-90?r=s*.5:(i=o*.5,r=o/2*n/90),e.x-=r,e.y-=i},_getTransformOrigin:function(e){var t;return e===0?t=[0,0]:e===90?t=[.5,1]:e===-90?t=[.5,0]:t=[0,.5],t},offsetNodeForTick:function(e){var t=this,n=t.get("leftTickOffset"),r=0-n;e.setStyle("left",r)},setCalculatedSize:function(){var e=this,t=e.get("styles"),n=t.label,r=this._totalTitleSize,i=Math.round(e.get("rightTickOffset")+e._maxLabelSize+r+n.margin.left);this._explicitWidth&&(i=this._explicitWidth),e.set("calculatedWidth",i),e.get("contentBox").setStyle("width",i)}},e.RightAxisLayout=f,l=function(){},l.prototype={_getDefaultMargins:function(){return{top:4,left:0,right:0,bottom:0}},setTickOffsets:function(){var e=this,t=e.get("styles").majorTicks,n=t.length,r=n*.5,i=t.display;e.set("leftTickOffset",0),e.set("rightTickOffset",0);switch(i){case"inside":e.set("topTickOffset",n),e.set("bottomTickOffset",0);break;case"outside":e.set("topTickOffset",0),e.set("bottomTickOffset",n);break;case"cross":e.set("topTickOffset",r),e.set("bottomTickOffset",r);break;default:e.set("topTickOffset",0),e.set("bottomTickOffset",0)}},getLineStart:function(){var e=this.get("styles"),t=e.padding,n=e.majorTicks,r=n.length,i=n.display,s={x:0,y:t.top};return i==="inside"?s.y+=r:i==="cross"&&(s.y+=r/2),s},drawTick:function(e,t,n){var r=this,i=r.get("styles"),s=i.padding,o=n.length,u={x:t.x,y:s.top},a={x:t.x,y:o+s.top};r.drawLine(e,u,a)},getLabelPoint:function(e){return{x:e.x,y:e.y+this.get("bottomTickOffset")}},updateMaxLabelSize:function(e,t){var n=this,r=this._labelRotationProps,i=r.rot,s=r.absRot,o=r.sinRadians,u=r.cosRadians,a;i===0?a=t:s===90?a=e:a=o*e+u*t,n._maxLabelSize=Math.max(n._maxLabelSize,a)},getExplicitlySized:function(e){if(this._explicitHeight){var t=this,n=t._explicitHeight,r=t._totalTitleSize,i=t.get("bottomTickOffset"),s=e.label.margin.right;return t._maxLabelSize=n-(i+s+r),!0}return!1},positionTitle:function(e){var t=this,n=t._titleBounds,r=t.get("styles").title.margin,i=t._titleRotationProps,s=n.bottom-n.top,o=e.offsetWidth,u=e.offsetHeight,a=t.get("width")*.5-o*.5,f=t.get("height")-u/2-s/2;i.labelWidth=o,i.labelHeight=u,r&&r.bottom&&(f-=r.bottom),i.x=a,i.y=f,i.transformOrigin=[.5,.5],t._rotate(e,i)},positionLabel:function(e,t,n,r){var i=this,s=i.get("bottomTickOffset"),o=n.label,u=0,a=i._labelRotationProps,f=a.rot,l=a.absRot,c=Math.round(t.x),h=Math.round(t.y),p=i._labelWidths[r],d=i._labelHeights[r];o.margin&&o.margin.top&&(u=o.margin.top),f>0?h-=d/2*f/90:f<0?(c-=p,h-=d/2*l/90):c-=p*.5,h+=u,h+=s,a.labelWidth=p,a.labelHeight=d,a.x=c,a.y=h,i._rotate(e,a)},_setRotationCoords:function(e){var t=e.rot,n=e.absRot,r=e.labelWidth,i=e.labelHeight,s,o;t>0?(s=0,o=i/2*t/90):t<0?(s=r,o=i/2*n/90):(s=r*.5,o=0),e.x-=s,e.y-=o},_getTransformOrigin:function(e){var t;return e>0?t=[0,.5]:e<0?t=[1,.5]:t=[0,0],t},offsetNodeForTick:function(e){var t=this;t.get("contentBox").setStyle("top",0-t.get("topTickOffset"))},setCalculatedSize:function(){var e=this,t=e.get("styles"),n=t.label,r=e._totalTitleSize,i=Math.round(e.get("bottomTickOffset")+e._maxLabelSize+n.margin.top+r);e._explicitHeight&&(i=e._explicitHeight),e.set("calculatedHeight",i)}},e.BottomAxisLayout=l,c=function(){},c.prototype={_getDefaultMargins:function(){return{top:0,left:0,right:0,bottom:4}},setTickOffsets:function(){var e=this,t=e.get("styles").majorTicks,n=t.length,r=n*.5,i=t.display;e.set("leftTickOffset",0),e.set("rightTickOffset",0);switch(i){case"inside":e.set("bottomTickOffset",n),e.set("topTickOffset",0);break;case"outside":e.set("bottomTickOffset",0),e.set("topTickOffset",n);break;case"cross":e.set("topTickOffset",r),e.set("bottomTickOffset",r);break;default:e.set("topTickOffset",0),e.set("bottomTickOffset",0)}},getLineStart:function(){var e=this,t=e.get("styles"),n=t.padding,r=t.majorTicks,i=r.length,s=r.display,o={x:0,y:n.top};return s==="outside"?o.y+=i:s==="cross"&&(o.y+=i/2),o},drawTick:function(e,t,n){var r=this,i=r.get("styles"),s=i.padding,o=n.length,u={x:t.x,y:s.top},a={x:t.x,y:o+s.top};r.drawLine(e,u,a)},getLabelPoint:function(e){return{x:e.x,y:e.y-this.get("topTickOffset")}},updateMaxLabelSize:function(e,t){var n=this,r=this._labelRotationProps,i=r.rot,s=r.absRot,o=r.sinRadians,u=r.cosRadians,a;i===0?a=t:s===90?a=e:a=o*e+u*t,n._maxLabelSize=Math.max(n._maxLabelSize,a)},getExplicitlySized:function(e){if(this._explicitHeight){var t=this,n=t._explicitHeight,r=t._totalTitleSize,i=t.get("topTickOffset"),s=e.label.margin.right;return t._maxLabelSize=n-(i+s+r),!0}return!1},positionTitle:function(e){var t=this,n=t._titleBounds,r=t.get("styles").title.margin,i=t._titleRotationProps,s=e.offsetWidth,o=e.offsetHeight,u=n.bottom-n.top,a=t.get("width")*.5-s*.5,f=u/2-o/2;i.labelWidth=s,i.labelHeight=o,r&&r.top&&(f+=r.top),i.x=a,i.y=f,i.transformOrigin=[.5,.5],t._rotate(e,i)},positionLabel:function(e,t,n,r){var i=this,s=this._totalTitleSize,o=i._maxLabelSize,u=t.x,a=t.y+s+o,f=this._labelRotationProps,l=f.rot,c=f.absRot,h=this._labelWidths[r],p=this._labelHeights[r];l===0?(u-=h*.5,a-=p):l===90?(u-=h,a-=p*.5):l===-90?a-=p*.5:l>0?(u-=h,a-=p-p*l/180):a-=p-p*c/180,f.x=Math.round(u),f.y=Math.round(a),f.labelWidth=h,f.labelHeight=p,this._rotate(e,f)},_setRotationCoords:function(e){var t=e.rot,n=e.absRot,r=e.labelWidth,i=e.labelHeight,s,o;t===0?(s=r*.5,o=i):t===90?(s=r,o=i*.5):t===-90?o=i*.5:t>0?(s=r,o=i-i*t/180):o=i-i*n/180,e.x-=s,e.y-=o},_getTransformOrigin:function(e){var t;return e===0?t=[0,0]:e===90?t=[1,.5]:e===-90?t=[0,.5]:e>0?t=[1,.5]:t=[0,.5],t},offsetNodeForTick:function(e){},setCalculatedSize:function(){var e=this,t=e.get("graphic"),n=e.get("styles"),r=n.label.margin,i=r.bottom+e._maxLabelSize,s=e._totalTitleSize,o=this.get("topTickOffset"),u=Math.round(o+i+s);this._explicitHeight&&(u=this._explicitWidth),e.set("calculatedHeight",u),t.set("y",u-o)}},e.TopAxisLayout=c,e.Axis=e.Base.create("axis",e.Widget,[e.Renderer],{_calculatedWidth:0,_calculatedHeight:0,_dataChangeHandler:function(e){this.get("rendered")&&this._drawAxis()},_positionChangeHandler:function(e){this._updateGraphic(e.newVal),this._updateHandler()},_updateGraphic:function(e){var t=this.get("graphic");e=="none"?t&&t.destroy():t||this._setCanvas()},_updateHandler:function(e){this.get("rendered")&&this._drawAxis()},renderUI:function(){this._updateGraphic(this.get("position"))},syncUI:function(){var e=this._layout,t,n,r,i,s;if(e){t=e._getDefaultMargins(),n=this.get("styles"),r=n.label.margin,i=n.title.margin;for(s in t)t.hasOwnProperty(s)&&(r[s]=r[s]===undefined?t[s]:r[s],i[s]=i[s]===undefined?t[s]:i[s])}this._drawAxis()},_setCanvas:function(){var t=this.get("contentBox"),n=this.get("boundingBox"),r=this.get("position"),i=this._parentNode,s=this.get("width"),o=this.get("height");n.setStyle("position","absolute"),n.setStyle("zIndex",2),s=s?s+"px":i.getStyle("width"),o=o?o+"px":i.getStyle("height"),r==="top"||r==="bottom"?t.setStyle("width",s):t.setStyle("height",o),t.setStyle("position","relative"),t.setStyle("left","0px"),t.setStyle("top","0px"),this.set("graphic",new e.Graphic),this.get("graphic").render(t)},_getDefaultStyles:function(){var t={majorTicks:{display:"inside",length:4,color:"#dad8c9",weight:1,alpha:1},minorTicks:{display:"none",length:2,color:"#dad8c9",weight:1},line:{weight:1,color:"#dad8c9",alpha:1},majorUnit:{determinant:"count",count:11,distance:75},top:"0px",left:"0px",width:"100px",height:"100px",label:{color:"#808080",alpha:1,fontSize:"85%",rotation:0,margin:{top:undefined,right:undefined,bottom:undefined,left:undefined}},title:{color:"#808080",alpha:1,fontSize:"85%",rotation:undefined,margin:{top:undefined,right:undefined,bottom:undefined,left:undefined}},hideOverlappingLabelTicks:!1};return e.merge(e.Renderer.prototype._getDefaultStyles(),t)},_handleSizeChange:function(e){var t=e.attrName,n=this.get("position"),r=n=="left"||n=="right",i=this.get("contentBox"),s=n=="bottom"||n=="top";i.setStyle("width",this.get("width")),i.setStyle("height",this.get("height")),(s&&t=="width"||r&&t=="height")&&this._drawAxis()},_layoutClasses:{top:c,bottom:l,left:a,right:f},drawLine:function(e,t,n){e.moveTo(t.x,t.y),e.lineTo(n.x,n.y)},_getTextRotationProps:function(e){if(e.rotation===undefined)switch(this.get("position")){case"left":e.rotation=-90;break;case"right":e.rotation=90;break;default:e.rotation=0}var t=Math.min(90,Math.max(-90,e.rotation)),n=Math.abs(t),r=Math.PI/180,i=parseFloat(parseFloat(Math.sin(n*r)).toFixed(8)),s=parseFloat(parseFloat(Math.cos(n*r)).toFixed(8));return{rot:t,absRot:n,radCon:r,sinRadians:i,cosRadians:s,textAlpha:e.alpha}},_drawAxis:function(){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1;if(this._layout){var e=this.get("styles"),t=e.line,n=e.label,r=e.majorTicks,i=r.display!="none",s,o=e.majorUnit,u,a,f=0,l=this._layout,c,h,p,d,v,m,g=this.get("labelFunction"),y=this.get("labelFunctionScope"),b=this.get("labelFormat"),w=this.get("graphic"),E=this.get("path"),S,x;this._labelWidths=[],this._labelHeights=[],w.set("autoDraw",!1),E.clear(),E.set("stroke",{weight:t.weight,color:t.color,opacity:t.alpha}),this._labelRotationProps=this._getTextRotationProps(n),this._labelRotationProps.transformOrigin=l._getTransformOrigin(this._labelRotationProps.rot),l.setTickOffsets.apply(this),c=this.getLength(),p=l.getLineStart.apply(this),u=this.getTotalMajorUnits(o),a=this.getMajorUnitDistance(u,c,o),this.set("edgeOffset",this.getEdgeOffset(u,c)*.5);if(u<1)this._clearLabelCache();else{s=this.getFirstPoint(p),this.drawLine(E,p,this.getLineEnd(s)),i&&(S=this.get("tickPath"),S.clear(),S.set("stroke",{weight:r.weight,color:r.color,opacity:r.alpha}),l.drawTick.apply(this,[S,s,r])),this._createLabelCache(),this._tickPoints=[],this._maxLabelSize=0,this._totalTitleSize=0,this._titleSize=0,this._setTitle(),x=l.getExplicitlySized.apply(this,[e]);for(;f<u;++f)i&&l.drawTick.apply(this,[S,s,r]),h=this.getPosition(s),d=this.getLabel(s,n),this._labels.push(d),this._tickPoints.push({x:s.x,y:s.y}),this.get("appendLabelFunction")(d,g.apply(y,[this.getLabelByIndex(f,u),b])),v=Math.round(d.offsetWidth),m=Math.round(d.offsetHeight),x||this._layout.updateMaxLabelSize.apply(this,[v,m]),this._labelWidths.push(v),this._labelHeights.push(m),s=this.getNextPoint(s,a);this._clearLabelCache(),this.get("overlapGraph")&&l.offsetNodeForTick.apply(this,[this.get("contentBox")]),l.setCalculatedSize.apply(this),this._titleTextField&&this._layout.positionTitle.apply(this,[this._titleTextField]);for(f=0;f<u;++f)l.positionLabel.apply(this,[this.get("labels")[f],this._tickPoints[f],e,f])}}this._drawing=!1,this._callLater?this._drawAxis():(this._updatePathElement(),this.fire("axisRendered"))},_setTotalTitleSize:function(t){var n=this._titleTextField,r=n.offsetWidth,i=n.offsetHeight,s=this._titleRotationProps.rot,o,u,a=t.margin,f=this.get("position"),l=new e.Matrix;l.rotate(s),o=l.getContentRect(r,i),f=="left"||f=="right"?(u=o.right-o.left,a&&(u+=a.left+a.right)):(u=o.bottom-o.top,a&&(u+=a.top+a.bottom)),this._titleBounds=o,this._totalTitleSize=u},_updatePathElement:function(){var e=this._path,t=this._tickPath,n=!1,r=this.get("graphic");e&&(n=!0,e.end()),t&&(n=!0,t.end()),n&&r._redraw()},_setTitle:function(){var e,t,n,r=this.get("title"),s=this._titleTextField,o;if(r!==null&&r!==undefined){n={rotation:"rotation",margin:"margin",alpha:"alpha"},t=this.get("styles").title,s?i.createElementNS||s.style.filter&&(s.style.filter=null):(s=i.createElement("span"),s.style.display="block",s.style.whiteSpace="nowrap",s.setAttribute("class","axisTitle"),this.get("contentBox").append(s)),s.style.position="absolute";for(e in t)t.hasOwnProperty(e)&&!n.hasOwnProperty(e)&&(s.style[e]=t[e]);this.get("appendTitleFunction")(s,r),this._titleTextField=s,this._titleRotationProps=this._getTextRotationProps(t),this._setTotalTitleSize(t)}else s&&(o=s.parentNode,o&&o.removeChild(s),this._titleTextField=null,this._totalTitleSize=0)},getLabel:function(t,n){var r,s,o=this._labelCache,u={rotation:"rotation",margin:"margin",alpha:"alpha"};o&&o.length>0?s=o.shift():(s=i.createElement("span"),s.className=e.Lang.trim([s.className,"axisLabel"].join(" ")),this.get("contentBox").append(s)),i.createElementNS||s.style.filter&&(s.style.filter=null),s.style.display="block",s.style.whiteSpace="nowrap",s.style.position="absolute";for(r in n)n.hasOwnProperty(r)&&!u.hasOwnProperty(r)&&(s.style[r]=n[r]);return s},_createLabelCache:function(){if(this._labels)while(this._labels.length>0)this._labelCache.push(this._labels.shift());else this._clearLabelCache();this._labels=[]},_clearLabelCache:function(){if(this._labelCache){var t=this._labelCache.length,n=0,r;for(;n<t;++n)r=this._labelCache[n],this._removeChildren(r),e.Event.purgeElement(r,!0),r.parentNode.removeChild(r)}this._labelCache=[]},getLineEnd:function(e){var t=this.get("width"),n=this.get("height"),r=this.get("position");return r==="top"||r==="bottom"?{x:t,y:e.y}:{x:e.x,y:n}},getLength:function(){var e,t=this.get("styles"),n=t.padding,r=this.get("width"),i=this.get("height"),s=this.get("position");return s==="top"||s==="bottom"?e=r-(n.left+n.right):e=i-(n.top+n.bottom),e},getFirstPoint:function(e){var t=this.get("styles"),n=this.get("position"),r=t.padding,i={x:e.x,y:e.y};return n==="top"||n==="bottom"?i.x+=r.left+this.get("edgeOffset"):i.y+=this.get("height")-(r.top+this.get("edgeOffset")),i},getNextPoint:function(e,t){var n=this.get("position");return n==="top"||n==="bottom"?e.x=e.x+t:e.y=e.y-t,e},getLastPoint:function(){var e=this.get("styles"),t=e.padding,n=this.get("width"),r=this.get("position");return r==="top"||r==="bottom"?{x:n-t.right,y:t.top}:{x:t.left,y:t.top}},getPosition:function(e){var t,n=this.get("height"),r=this.get("styles"),i=r.padding,s=this.get("position"),o=this.get("dataType");return s==="left"||s==="right"?o==="numeric"?t=n-(i.top+i.bottom)-(e.y-i.top):t=e.y-i.top:t=e.x-i.left,t},_rotate:function(t,n){var r=n.rot,o=n.x,a=n.y,f,l,c=new e.Matrix,h=n.transformOrigin||[0,0],p;i.createElementNS?(c.translate(o,a),c.rotate(r),u.setStyle(t,"transformOrigin",h[0]*100+"% "+h[1]*100+"%"),u.setStyle(t,"transform",c.toCSSText())):(l=n.textAlpha,s.isNumber(l)&&l<1&&l>-1&&!isNaN(l)&&(f="progid:DXImageTransform.Microsoft.Alpha(Opacity="+Math.round(l*100)+")"),r!==0?(c.rotate(r),p=c.getContentRect(n.labelWidth,n.labelHeight),c.init(),c.translate(p.left,p.top),c.translate(o,a),this._simulateRotateWithTransformOrigin(c,r,h,n.labelWidth,n.labelHeight),f?f+=" ":f="",f+=c.toFilterText(),t.style.left=c.dx+"px",t.style.top=c.dy+"px"):(t.style.left=o+"px",t.style.top=a+"px"),f&&(t.style.filter=f))},_simulateRotateWithTransformOrigin:function(e,t,n,r,i){var s=n[0]*r,o=n[1]*i;s=isNaN(s)?0:s,o=isNaN(o)?0:o,e.translate(s,o),e.rotate(t),e.translate(-s,-o)},getMaxLabelBounds:function(){return this._getLabelBounds(this.getMaximumValue())},getMinLabelBounds:function(){return this._getLabelBounds(this.getMinimumValue())},_getLabelBounds:function(t){var n=this._layout,r=this.get("styles").label,i=new e.Matrix,s,o=this._getTextRotationProps(r);return o.transformOrigin=n._getTransformOrigin(o.rot),s=this.getLabel({x:0,y:0},r),this.get("appendLabelFunction")(s,this.get("labelFunction").apply(this,[t,this.get("labelFormat")])),o.labelWidth=s.offsetWidth,o.labelHeight=s.offsetHeight,this._removeChildren(s),e.Event.purgeElement(s,!0),s.parentNode.removeChild(s),o.x=0,o.y=0,n._setRotationCoords(o),i.translate(o.x,o.y),this._simulateRotateWithTransformOrigin(i,o.rot,o.transformOrigin,o.labelWidth,o.labelHeight),i.getContentRect(o.labelWidth,o.labelHeight)},_removeChildren:function(e){if(e.hasChildNodes()){var t;while(e.firstChild)t=e.firstChild,this._removeChildren(t),e.removeChild(t)}},destructor:function(){var e=this.get("contentBox").getDOMNode(),t=this.get("labels"),n=this.get("graphic"),r,i=t?t.length:0;if(i>0)while(t.length>0)r=t.shift(),this._removeChildren(r),e.removeChild(r),r=null;n&&n.destroy()},_maxLabelSize:0,_setText:function(e,t){e.innerHTML="",s.isNumber(t)?t+="":t||(t=""),o(t)&&(t=i.createTextNode(t)),e.appendChild(t)}},{ATTRS:{width:{lazyAdd:!1,getter:function(){return this._explicitWidth?this._explicitWidth:this._calculatedWidth},setter:function(e){return this._explicitWidth=e,e}},height:{lazyAdd:!1,getter:function(){return this._explicitHeight?this._explicitHeight:this._calculatedHeight},setter:function(e){return this._explicitHeight=e,e}},calculatedWidth:{getter:function(){return this._calculatedWidth},setter:function(e){return this._calculatedWidth=e,e}},calculatedHeight:{getter:function(){return this._calculatedHeight},setter:function(e){return this._calculatedHeight=e,e}},edgeOffset:{value:0},graphic:{},path:{readOnly:!0,getter:function(){if(!this._path){var e=this.get("graphic");e&&(this._path=e.addShape({type:"path"}))}return this._path}},tickPath:{readOnly:!0,getter:function(){if(!this._tickPath){var e=this.get("graphic");e&&(this._tickPath=e.addShape({type:"path"}))}return this._tickPath}},node:{},position:{setter:function(e){var t=this._layoutClasses[e];return e&&e!="none"&&(this._layout=new t),e}},topTickOffset:{value:0},bottomTickOffset:{value:0},leftTickOffset:{value:0},rightTickOffset:{value:0},labels:{readOnly:!0,getter:function(){return this._labels}},tickPoints:{readOnly:!0,getter:function(){return this.get("position")=="none"?this.get("styles").majorUnit.count:this._tickPoints}},overlapGraph:{value:!0,validator:function(e){return s.isBoolean(e)}},labelFunctionScope:{},maxLabelSize:{getter:function(){return this._maxLabelSize},setter:function(e){return this._maxLabelSize=e,e}},title:{value:null},labelFunction:{value:function(e,t){return e}},appendLabelFunction:{valueFn:function(){return this._setText}},appendTitleFunction:{valueFn:function(){return this._setText}}}}),e.AxisType=e.Base.create("baseAxis",e.Axis,[],{initializer:function(){this.after("dataReady",e.bind(this._dataChangeHandler,this)),this.after("dataUpdate",e.bind(this._dataChangeHandler,this)),this.after("minimumChange",e.bind(this._keyChangeHandler,this)),this.after("maximumChange",e.bind(this._keyChangeHandler,this)),this.after("keysChange",this._keyChangeHandler),this.after("dataProviderChange",this._dataProviderChangeHandler),this.after("alwaysShowZeroChange",this._keyChangeHandler),this.after("roundingMethodChange",this._keyChangeHandler)},bindUI:function(){this.after("stylesChange",this._updateHandler),this.after("overlapGraphChange",this._updateHandler),this.after("positionChange",this._positionChangeHandler),this.after("widthChange",this._handleSizeChange),this.after("heightChange",this._handleSizeChange),this.after("calculatedWidthChange",this._handleSizeChange),this.after("calculatedHeightChange",this._handleSizeChange)},_dataProviderChangeHandler:function(e){var t=this.get("keyCollection").concat(),n=this.get("keys"),r;if(n)for(r in n)n.hasOwnProperty(r)&&delete n[r];t&&t.length&&this.set("keys",t)},GUID:"yuibaseaxis",_type:null,_setMaximum:null,_dataMaximum:null,_setMinimum:null,_data:null,_updateTotalDataFlag:!0,_dataReady:!1,addKey:function(e){this.set("keys",e)},_getKeyArray:function(e,t){var n=0,r,i=[],s=t.length;for(;n<s;++n)r=t[n],i[n]=r[e];return i},_setDataByKey:function(e,t){var n,r,i=[],s=this._dataClone.concat(),o=s.length;for(n=0;n<o;++n)r=s[n],i[n]=r[e];this.get("keys")[e]=i,this._updateTotalDataFlag=!0},_updateTotalData:function(){var e=this.get("keys"),t;this._data=[];for(t in e)e.hasOwnProperty(t)&&(this._data=this._data.concat(e[t]));this._updateTotalDataFlag=!1},removeKey:function(e){var t=this.get("keys");t.hasOwnProperty(e)&&(delete t[e],this._keyChangeHandler())},getKeyValueAt:function(e,t){var n=NaN,r=this.get("keys");return r[e]&&s.isNumber(parseFloat(r[e][t]))&&(n=r[e][t]),parseFloat(n)},getDataByKey:function(e){var t=this.get("keys");return t[e]?t[e]:null},_updateMinAndMax:function(){var e=this.get("data"),t=0,n=0,r,i,s;if(e&&e.length&&e.length>0){r=e.length,t=n=e[0];if(r>1)for(s=1;s<r;s++){i=e[s];if(isNaN(i))continue;t=Math.max(i,t),n=Math.min(i,n)}}this._dataMaximum=t,this._dataMinimum=n},getTotalMajorUnits:function(){var e,t=this.get("styles").majorUnit,n=this.get("length");return t.determinant==="count"?e=t.count:t.determinant==="distance"&&(e=n/t.distance+1),e},getMajorUnitDistance:function(e,t,n){var r;return n.determinant==="count"?r=t/(e-1):n.determinant==="distance"&&(r=n.distance),r},getEdgeOffset:function(e,t){return 0},getLabelByIndex:function(e,t){var n=this.get("minimum"),r=this.get("maximum"),i=(r-n)/(t-1),s;return t-=1,s=n+e*i,s},_keyChangeHandler:function(e){this._updateMinAndMax(),this.fire("dataUpdate")},_hasDataOverflow:function(){return this.get("setMin")||this.get("setMax")?!0:!1},getMinimumValue:function(){return this.get("minimum")},getMaximumValue:function(){return this.get("maximum")}},{ATTRS:{keys:{value:{},setter:function(e){var t={},n,r,i=this.get("dataProvider");if(s.isArray(e)){r=e.length;for(n=0;n<r;++n)t[e[n]]=this._getKeyArray(e[n],i)}else if(s.isString(e))t=this.get("keys"),t[e]=this._getKeyArray(e,i);else for(n in e)e.hasOwnProperty(n)&&(t[n]=this._getKeyArray(n,i));return this._updateTotalDataFlag=!0,t}},roundingMethod:{value:"niceNumber"},type:{readOnly:!0,getter:function(){return this._type}},dataProvider:{setter:function(e){return e}},dataMaximum:{getter:function(){return this._dataMaximum||this._updateMinAndMax(),this._dataMaximum}},maximum:{lazyAdd:!1,getter:function(){var e=this.get("dataMaximum"),t=this.get("minimum");return t===0&&e===0&&(e=10),s.isNumber(this._setMaximum)&&(e=this._setMaximum),parseFloat(e)},setter:function(e){return this._setMaximum=parseFloat(e),e}},dataMinimum:{getter:function(){return this._dataMinimum||this._updateMinAndMax(),this._dataMinimum}},minimum:{lazyAdd:!1,getter:function(){var e=this.get("dataMinimum");return s.isNumber(this._setMinimum)&&(e=this._setMinimum),parseFloat(e)},setter:function(e){return this._setMinimum=parseFloat(e),e}},setMax:{readOnly:!0,getter:function(){return s.isNumber(this._setMaximum)}},setMin:{readOnly:!0,getter:function(){return s.isNumber(this._setMinimum)}},data:{getter:function(){return(!this._data||this._updateTotalDataFlag)&&this._updateTotalData(),this._data}},keyCollection:{getter:function(){var e=this.get("keys"),t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push(t);return n},readOnly:!0}}}),w.NAME="numericAxis",w.ATTRS={alwaysShowZero:{value:!0},labelFunction:{value:function(t,n){return n?e.DataType.Number.format(t,n):t}},labelFormat:{value:{prefix:"",thousandsSeparator:"",decimalSeparator:"",decimalPlaces:"0",suffix:""}}},e.extend(w,e.AxisType,{formatLabel:function(t,n){return n?e.DataType.Number.format(t,n):t},getTotalByKey:function(e){var t=0,n=this.getDataByKey(e),r=0,i,s=n?n.length:0;for(;r<s;++r)i=parseFloat(n[r]),isNaN(i)||(t+=i);return t},_type:"numeric",_getMinimumUnit:function(e,t,n){return this._getNiceNumber(Math.ceil((e-t)/n))},_getNiceNumber:function(e){var t=e,n=Math.ceil(Math.log(t)*.4342944819032518),r=Math.pow(10,n),i;return r/2>=t?(i=Math.floor((r/2-t)/(Math.pow(10,n-1)/2)),t=r/2-i*Math.pow(10,n-1)/2):t=r,isNaN(t)?e:t},_updateMinAndMax:function(){var e=this.get("data"),t,n,r,i,o=0,u,a=this.get("setMax"),f=this.get("setMin");if(!a||!f){if(e&&e.length&&e.length>0){r=e.length;for(;o<r;o++){i=e[o];if(isNaN(i)){if(s.isObject(i)){n=t=0;for(u in i)i.hasOwnProperty(u)&&(t=Math.max(i[u],t),n=Math.min(i[u],n))}t=a?this._setMaximum:t,n=f?this._setMinimum:n;continue}f?n=this._setMinimum:n===undefined?n=i:n=Math.min(i,n),a?t=this._setMaximum:t===undefined?t=i:t=Math.max(i,t),this._actualMaximum=t,this._actualMinimum=n}}this._roundMinAndMax(n,t,f,a)}},_roundMinAndMax:function(e,t,n,r){var i,s,o=e>=0,u=t>0,a,f,l,c,h,p,d,v=this.getTotalMajorUnits()-1,m=this.get("alwaysShowZero"),g=this.get("roundingMethod"),y=(t-e)/v>=1;if(g)if(g=="niceNumber"){i=this._getMinimumUnit(t,e,v);if(o&&u)(m||e<i)&&!n?(e=0,i=this._getMinimumUnit(t,e,v)):e=this._roundDownToNearest(e,i),r?m||(e=t-i*v):n?t=e+i*v:t=this._roundUpToNearest(t,i);else if(u&&!o)if(m){c=Math.round(v/(-1*e/t+1)),c=Math.max(Math.min(c,v-1),1),h=v-c,p=Math.ceil(t/c),d=Math.floor(e/h)*-1;if(n){while(d<p&&h>=0)h--,c++,p=Math.ceil(t/c),d=Math.floor(e/h)*-1;h>0?t=d*c:t=e+i*v}else if(r){while(p<d&&c>=0)h++,c--,d=Math.floor(e/h)*-1,p=Math.ceil(t/c);c>0?e=p*h*-1:e=t-i*v}else i=Math.max(p,d),i=this._getNiceNumber(i),t=i*c,e=i*h*-1}else r?e=t-i*v:n?t=e+i*v:(e=this._roundDownToNearest(e,i),t=this._roundUpToNearest(t,i));else n?m?t=0:t=e+i*v:r?e=t-i*v:m||t===0||t+i>0?(t=0,i=this._getMinimumUnit(t,e,v),e=t-i*v):(e=this._roundDownToNearest(e,i),t=this._roundUpToNearest(t,i))}else g=="auto"?o&&u?((m||e<(t-e)/v)&&!n&&(e=0),i=(t-e)/v,y&&(i=Math.ceil(i)),t=e+i*v):u&&!o?m?(c=Math.round(v/(-1*e/t+1)),c=Math.max(Math.min(c,v-1),1),h=v-c,y?(p=Math.ceil(t/c),d=Math.floor(e/h)*-1):(p=t/c,d=e/h*-1),i=Math.max(p,d),t=i*c,e=i*h*-1):(i=(t-e)/v,y&&(i=Math.ceil(i)),e=this._roundDownToNearest(e,i),t=this._roundUpToNearest(t,i)):(i=(t-e)/v,y&&(i=Math.ceil(i)),m||t===0||t+i>0?(t=0,i=(t-e)/v,y&&Math.ceil(i),e=t-i*v):(e=this._roundDownToNearest(e,i),t=this._roundUpToNearest(t,i))):!isNaN(g)&&isFinite(g)&&(i=g,s=i*v,a=t-e>s,l=this._roundDownToNearest(e,i),f=this._roundUpToNearest(t,i),r?e=t-s:n?t=e+s:o&&u?(m||l<=0?e=0:e=l,t=e+s):u&&!o?(e=l,t=f):(m||f>=0?t=0:t=f,e=t-s));this._dataMaximum=t,this._dataMinimum=e},getLabelByIndex:function(e,t){var n=this.get("minimum"),r=this.get("maximum"),i=(r-n)/(t-1),s,o=this.get("roundingMethod");return t-=1,e===0?s=n:e===t?s=r:(s=e*i,o=="niceNumber"&&(s=this._roundToNearest(s,i)),s+=n),parseFloat(s)},_roundToNearest:function(e,t){t=t||1;if(t===0)return e;var n=Math.round(this._roundToPrecision(e/t,10))*t;return this._roundToPrecision(n,10)},_roundUpToNearest:function(e,t){return t=t||1,t===0?e:Math.ceil(this._roundToPrecision(e/t,10))*t},_roundDownToNearest:function(e,t){return t=t||1,t===0?e:Math.floor(this._roundToPrecision(e/t,10))*t},_roundToPrecision:function(e,t){t=t||0;var n=Math.pow(10,t);return Math.round(n*e)/n},_hasDataOverflow:function(){var e,t,n;return this.get("setMin")||this.get("setMax")?!0:(e=this.get("roundingMethod"),t=this._actualMinimum,n=this._actualMaximum,s.isNumber(e)&&(s.isNumber(n)&&n>this._dataMaximum||s.isNumber(t)&&t<this._dataMinimum)?!0:!1)}}),e.NumericAxis=w,E.NAME="stackedAxis",e.extend(E,e.NumericAxis,{_updateMinAndMax:function(){var e=0,t=0,n=0,r=0,i=0,s=0,o,u,a=this.get("keys"),f=this.get("setMin"),l=this.get("setMax");for(o in a)a.hasOwnProperty(o)&&(i=Math.max(i,a[o].length));for(;s<i;++s){n=0,r=0;for(o in a)if(a.hasOwnProperty(o)){u=a[o][s];if(isNaN(u))continue;u>=0?n+=u:r+=u}n>0?e=Math.max(e,n):e=Math.max(e,r),r<0?t=Math.min(t,r):t=Math.min(t,n)}this._actualMaximum=e,this._actualMinimum=t,l&&(e=this._setMaximum),f&&(t=this._setMinimum),this._roundMinAndMax(t,e,f,l)}}),e.StackedAxis=E,S.NAME="timeAxis",S.ATTRS={setMax:{readOnly:!0,getter:function(){var e=this._getNumber(this._setMaximum);return s.isNumber(e)}},setMin:{readOnly:!0,getter:function(){var e=this._getNumber(this._setMinimum);return s.isNumber(e)}},maximum:{getter:function(){var e=this._getNumber(this._setMaximum);return s.isNumber(e)||(e=this._getNumber(this.get("dataMaximum"))),parseFloat(e)},setter:function(e){return this._setMaximum=this._getNumber(e),e}},minimum:{getter:function(){var e=this._getNumber(this._setMinimum);return s.isNumber(e)||(e=this._getNumber(this.get("dataMinimum"))),parseFloat(e)},setter:function(e){return this._setMinimum=this._getNumber(e),e}},labelFunction:{value:function(t,n){return t=e.DataType.Date.parse(t),n?e.DataType.Date.format(t,{format:n}):t}},labelFormat:{value:"%b %d, %y"}},e.extend(S,e.AxisType,{formatLabel:function(t,n){return t=e.DataType.Date.parse(t),n?e.DataType.Date.format(t,{format:n}):t},GUID:"yuitimeaxis",_dataType:"time",getLabelByIndex:function(e,t){var n=this.get("minimum"),r=this.get("maximum"),i=this.get("position"),s,o;return t-=1,s=(r-n)/t*e,i=="bottom"||i=="top"?o=n+s:o=r-s,o},_getKeyArray:function(e,t){var n,r=[],i=0,o,u=t.length;for(;i<u;++i)n=t[i][e],s.isDate(n)?o=n.valueOf():(o=new Date(n),s.isDate(o)?o=o.valueOf():s.isNumber(n)?o=n:s.isNumber(parseFloat(n))?o=parseFloat(n):(typeof n!="string"&&(n=n),o=(new Date(n)).valueOf())),r[i]=o;return r},_setDataByKey:function(e,t){var n,r=[],i=this._dataClone.concat(),o,u,a=i.length;for(o=0;o<a;++o)n=i[o][e],s.isDate(n)?u=n.valueOf():(u=new Date(n),s.isDate(u)?u=u.valueOf():s.isNumber(n)?u=n:s.isNumber(parseFloat(n))?u=parseFloat(n):(typeof n!="string"&&(n=n.toString()),u=(new Date(n)).valueOf())),r[o]=u;this.get("keys")[e]=r,this._updateTotalDataFlag=!0},_getNumber:function(e){return s.isDate(e)?e=e.valueOf():!s.isNumber(e)&&e&&(e=(new Date(e)).valueOf()),e}}),e.TimeAxis=S,x.NAME="categoryAxis",e.extend(x,e.AxisType,{formatLabel:function(e,t){return e},_indices:null,GUID:"yuicategoryaxis",_type:"category",_updateMinAndMax:function(){this._dataMaximum=Math.max(this.get("data").length-1,0),this._dataMinimum=0},_getKeyArray:function(e,t){var n=0,r,i=[],s=[],o=t.length;this._indices||(this._indices={});for(;n<o;++n)r=t[n],i[n]=n,s[n]=r[e];return this._indices[e]=i,s},_setDataByKey:function(e){var t,n,r=[],i=[],s=this._dataClone.concat(),o=s.length;this._indices||(this._indices={});for(t=0;t<o;++t)n=s[t],r[t]=t,i[t]=n[e];this._indices[e]=r,this.get("keys")[e]=i.concat(),this._updateTotalDataFlag=!0},getDataByKey:function(e){this._indices||this.get("keys");var t=this._indices;return t[e]?t[e]:null},getTotalMajorUnits:function(e,t){return this.get("data").length},getMajorUnitDistance:function(e,t,n){var r;return n.determinant==="count"?r=t/e:n.determinant==="distance"&&(r=n.distance),r},getEdgeOffset:function(e,t){return t/e},getKeyValueAt:function(e,t){var n=NaN,r=this.get("keys");return r[e]&&r[e][t]&&(n=r[e][t]),n},getLabelByIndex:function(e,t){var n,r=this.get("data"),i=this.get("position");return i=="bottom"||i=="top"?n=r[e]:n=r[t-(e+1)],n},getMinimumValue:function(){var e=this.get("data"),t=e[0];return t},getMaximumValue:function(){var e=this.get("data"),t=e.length-1,n=e[t];return n}}),e.CategoryAxis=x,T.prototype={getCurveControlPoints:function(e,t){var n=[],r=1,i=e.length-1,s=[],o=[];if(i<1)return null;n[0]={startx:e[0],starty:t[0],endx:e[1],endy:t[1]};if(i===1)return n[0].ctrlx1=(2*e[0]+e[1])/3,n[0].ctrly2=(2*t[0]+t[1])/3,n[0].ctrlx2=2*n[0].ctrlx1-e[0],n[0].ctrly2=2*n[0].ctrly1-t[0],n;for(;r<i;++r)n.push({startx:Math.round(e[r]),starty:Math.round(t[r]),endx:Math.round(e[r+1]),endy:Math.round(t[r+1])}),s[r]=4*e[r]+2*e[r+1],o[r]=4*t[r]+2*t[r+1];s[0]=e[0]+2*e[1],s[i-1]=(8*e[i-1]+e[i])/2,s=this.getControlPoints(s.concat()),o[0]=t[0]+2*t[1],o[i-1]=(8*t[i-1]+t[i])/2,o=this.getControlPoints(o.concat());for(r=0;r<i;++r)n[r].ctrlx1=Math.round(s[r]),n[r].ctrly1=Math.round(o[r]),r<i-1?(n[r].ctrlx2=Math.round(2*e[r+1]-s[r+1]),n[r].ctrly2=Math.round(2*t[r+1]-o[r+1])):(n[r].ctrlx2=Math.round((e[i]+s[i-1])/2),n[r].ctrly2=Math.round((t[i]+o[i-1])/2));return n},getControlPoints:function(e){var t=e.length,n=[],r=[],i=2,s=1;n[0]=e[0]/i;for(;s<t;++s)r[s]=1/i,i=(s<t-1?4:3.5)-r[s],n[s]=(e[s]-n[s-1])/i;for(s=1;s<t;++s)n[t-s-1]-=r[t-s]*n[t-s];return n}},e.CurveUtil=T,N.prototype={_stacked:!0,_stackCoordinates:function(){this.get("direction")=="vertical"?this._stackXCoords():this._stackYCoords()},_stackXCoords:function(){var e=this.get("order"),t=this.get("type"),n=this.get("graph"),r=n.seriesTypes[t],i=0,o=this.get("xcoords"),u=this.get("ycoords"),a,f,l,c,h=o.concat(),p,d,v=[],m;e>0?(p=r[e-1].get("stackedXCoords"),d=r[e-1].get("stackedYCoords"),a=p.length):a=o.length;for(;i<a;i+=1)if(s.isNumber(o[i])){if(e>0){l=p[i];if(!s.isNumber(l)){c=e;while(c>-1&&!s.isNumber(l))c-=1,c>-1?l=r[c].get("stackedXCoords")[i]:l=this._leftOrigin}o[i]=o[i]+l}h[i]=o[i]}else v.push(i);this._cleanXNaN(h,u),a=v.length;if(a>0)for(i=0;i<a;i+=1)m=v[i],f=e>0?p[m]:this._leftOrigin,h[m]=Math.max(h[m],f);this.set("stackedXCoords",h),this.set("stackedYCoords",u)},_stackYCoords:function(){var e=this.get("order"),t=this.get("type"),n=this.get("graph"),r=n.get("height"),i=n.seriesTypes[t],o=0,u=this.get("xcoords"),a=this.get("ycoords"),f,l,c,h,p=a.concat(),d,v,m=[],g;e>0?(d=i[e-1].get("stackedXCoords"),v=i[e-1].get("stackedYCoords"),f=v.length):f=a.length;for(;o<f;o+=1)if(s.isNumber(a[o])){if(e>0){c=v[o];if(!s.isNumber(c)){h=e;while(h>-1&&!s.isNumber(c))h-=1,h>-1?c=i[h].get("stackedYCoords")[o]:c=this._bottomOrigin}a[o]=c-(r-a[o])}p[o]=a[o]}else m.push(o);this._cleanYNaN(u,p),f=m.length;if(f>0)for(o=0;o<f;o+=1)g=m[o],l=e>0?v[g]:r,p[g]=Math.min(p[g],l);this.set("stackedXCoords",u),this.set("stackedYCoords",p)},_cleanXNaN:function(e,t){var n,r,i,o,u,a,f,l,c=s.isNumber,h,p=0,d=t.length;for(;p<d;++p)u=e[p],a=t[p],!c(u)&&p>0&&p<d-1&&(o=t[p-1],i=this._getPreviousValidCoordValue(e,p),l=t[p+1],f=this._getNextValidCoordValue(e,p),c(i)&&c(f)&&(h=(l-o)/(f-i),e[p]=(a+h*i-o)/h),n=NaN,r=NaN)},_getPreviousValidCoordValue:function(e,t){var n,r=s.isNumber,i=-1;while(!r(n)&&t>i)t-=1,n=e[t];return n},_getNextValidCoordValue:function(e,t){var n,r=s.isNumber,i=e.length;while(!r(n)&&t<i)t+=1,n=e[t];return n},_cleanYNaN:function(e,t){var n,r,i,o,u,a,f,l,c=s.isNumber,h,p=0,d=e.length;for(;p<d;++p)u=e[p],a=t[p],!c(a)&&p>0&&p<d-1&&(i=e[p-1],o=this._getPreviousValidCoordValue(t,p),f=e[p+1],l=this._getNextValidCoordValue(t,p),c(o)&&c(l)&&(h=(l-o)/(f-i),t[p]=o+(h*u-h*i)),n=NaN,r=NaN)}},e.StackingUtil=N,C.prototype={_lineDefaults:null,_getGraphic:function(){var e=this.get("graphic")||this.get("graph").get("graphic");return this._lineGraphic||(this._lineGraphic=e.addShape({type:"path"})),this._lineGraphic.clear(),this._lineGraphic},_toggleVisible:function(e){this._lineGraphic&&this._lineGraphic.set("visible",e)},drawLines:function(){if(this.get("xcoords").length<1)return;var e=s.isNumber,t,n,r=this.get("direction"),i,o,u,a=!0,f,l,c,h,p,d=this.get("styles").line,v=d.lineType,m=d.color||this._getDefaultColor(this.get("graphOrder"),"line"),g=d.alpha,y=d.dashLength,b=d.gapSpace,w=d.connectDiscontinuousPoints,E=d.discontinuousType,S=d.discontinuousDashLength,x=d.discontinuousGapSpace,T=this._getGraphic();this._stacked?(t=this.get("stackedXCoords"),n=this.get("stackedYCoords")):(t=this.get("xcoords"),n=this.get("ycoords")),i=r==="vertical"?n.length:t.length,T.set("stroke",{weight:d.weight,color:m,opacity:g});for(p=0;p<i;p=++p){c=t[p],h=n[p],u=e(c)&&e(h);if(!u){o=u;continue}a?(a=!1,T.moveTo(c,h)):o?v!="dashed"?T.lineTo(c,h):this.drawDashedLine(T,f,l,c,h,y,b):w?E!="solid"?this.drawDashedLine(T,f,l,c,h,S,x):T.lineTo(c,h):T.moveTo(c,h),f=c,l=h,o=!0}T.end()},drawSpline:function(){if(this.get("xcoords").length<1)return;var e=this.get("xcoords"),t=this.get("ycoords"),n=this.getCurveControlPoints(e,t),r=n.length,i,s,o,u,a,f,l=0,c=this.get("styles").line,h=this._getGraphic(),p=c.alpha,d=c.color||this._getDefaultColor(this.get("graphOrder"),"line");h.set("stroke",{weight:c.weight,color:d,opacity:p}),h.moveTo(e[0],t[0]);for(;l<r;l=++l)a=n[l].endx,f=n[l].endy,i=n[l].ctrlx1,s=n[l].ctrlx2,o=n[l].ctrly1,u=n[l].ctrly2,h.curveTo(i,o,s,u,a,f);h.end()},drawDashedLine:function(e,t,n,r,i,s,o){s=s||10,o=o||10;var u=s+o,a=r-t,f=i-n,l=Math.sqrt(Math.pow(a,2)+Math.pow(f,2)),c=Math.floor(Math.abs(l/u)),h=Math.atan2(f,a),p=t,d=n,v;a=Math.cos(h)*u,f=Math.sin(h)*u;for(v=0;v<c;++v)e.moveTo(p,d),e.lineTo(p+Math.cos(h)*s,d+Math.sin(h)*s),p+=a,d+=f;e.moveTo(p,d),l=Math.sqrt((r-p)*(r-p)+(i-d)*(i-d)),l>s?e.lineTo(p+Math.cos(h)*s,d+Math.sin(h)*s):l>0&&e.lineTo(p+Math.cos(h)*l,d+Math.sin(h)*l),e.moveTo(r,i)},_getLineDefaults:function(){return{alpha:1,weight:6,lineType:"solid",dashLength:10,gapSpace:10,connectDiscontinuousPoints:!0,discontinuousType:"solid",discontinuousDashLength:10,discontinuousGapSpace:10}}},e.augment(C,e.Attribute),e.Lines=C,k.prototype={_getPath:function(){var e=this._path;return e||(e=this.get("graph").get("graphic").addShape({type:"path"}),this._path=e),e},_toggleVisible:function(e){this._path&&this._path.set("visible",e)},drawFill:function(e,t){if(e.length<1)return;var n=s.isNumber,r=e.length,i=e[0],o=t[0],u=i,a=o,f,l,c,h=!0,p=0,d=this.get("styles").area,v=this._getPath(),m=d.color||this._getDefaultColor(this.get("graphOrder"),"slice");v.clear(),v.set("fill",{color:m,opacity:d.alpha}),v.set("stroke",{weight:0});for(;p<r;p=++p){f=e[p],l=t[p],c=n(f)&&n(l);if(!c)continue;h?(this._firstValidX=f,this._firstValidY=l,h=!1,v.moveTo(f,l)):v.lineTo(f,l),u=f,a=l}this._lastValidX=u,this._lastValidY=a,v.end()},drawAreaSpline:function(){if(this.get("xcoords").length<1)return;var e=this.get("xcoords"),t=this.get("ycoords"),n=this.getCurveControlPoints(e,t),r=n.length,i,s,o,u,a,f,l=0,c=e[0],h=t[0],p=this.get("styles").area,d=this._getPath(),v=p.color||this._getDefaultColor(this.get("graphOrder"),"slice");d.set("fill",{color:v,opacity:p.alpha}),d.set("stroke",{weight:0}),d.moveTo(c,h);for(;l<r;l=++l)a=n[l].endx,f=n[l].endy,i=n[l].ctrlx1,s=n[l].ctrlx2,o=n[l].ctrly1,u=n[l].ctrly2,d.curveTo(i,o,s,u,a,f);this.get("direction")==="vertical"?(d.lineTo(this._leftOrigin,f),d.lineTo(this._leftOrigin,h)):(d.lineTo(a,this._bottomOrigin),d.lineTo(c,this._bottomOrigin)),d.lineTo(c,h),d.end()},drawStackedAreaSpline:function(){if(this.get("xcoords").length<1)return;var e=this.get("xcoords"),t=this.get("ycoords"),n,r=this.get("order"),i=this.get("type"),s=this.get("graph"),o=s.seriesTypes[i],u,a,f,l,c,h,p,d,v,m=0,g,y,b=this.get("styles").area,w=this._getPath(),E=b.color||this._getDefaultColor(this.get("graphOrder"),"slice");g=e[0],y=t[0],n=this.getCurveControlPoints(e,t),f=n.length,w.set("fill",{color:E,opacity:b.alpha}),w.set("stroke",{weight:0}),w.moveTo(g,y);for(;m<f;m=++m)d=n[m].endx,v=n[m].endy,l=n[m].ctrlx1,c=n[m].ctrlx2,h=n[m].ctrly1,p=n[m].ctrly2,w.curveTo(l,h,c,p,d,v);if(r>0){u=o[r-1].get("xcoords").concat().reverse(),a=o[r-1].get("ycoords").concat().reverse(),n=this.getCurveControlPoints(u,a),m=0,f=n.length,w.lineTo(u[0],a[0]);for(;m<f;m=++m)d=n[m].endx,v=n[m].endy,l=n[m].ctrlx1,c=n[m].ctrlx2,h=n[m].ctrly1,p=n[m].ctrly2,w.curveTo(l,h,c,p,d,v)}else this.get("direction")==="vertical"?(w.lineTo(this._leftOrigin,t[t.length-1]),w.lineTo(this._leftOrigin,y)):(w.lineTo(e[e.length-1],this._bottomOrigin),w.lineTo(g,this._bottomOrigin));w.lineTo(g,y),w.end()},_defaults:null,_getClosingPoints:function(){var e=this.get("xcoords").concat(),t=this.get("ycoords").concat(),n,r;return this.get("direction")==="vertical"?(r=this._getLastValidIndex(e),n=this._getFirstValidIndex(e),t.push(t[r]),t.push(t[n]),e.push(this._leftOrigin),e.push(this._leftOrigin)):(r=this._getLastValidIndex(t),n=this._getFirstValidIndex(t),e.push(e[r]),e.push(e[n]),t.push(this._bottomOrigin),t.push(this._bottomOrigin)),e.push(e[0]),t.push(t[0]),[e,t]},_getHighestValidOrder:function(e,t,n,r){var i=r=="vertical"?"stackedXCoords":"stackedYCoords",s;while(isNaN(s)&&n>-1)n-=1,n>-1&&(s=e[n].get(i)[t]);return n},_getCoordsByOrderAndIndex:function(e,t,n,r){var i,s;return r=="vertical"?(i=n<0?this._leftOrigin:e[n].get("stackedXCoords")[t],s=this.get("stackedYCoords")[t]):(i=this.get("stackedXCoords")[t],s=n<0?this._bottomOrigin:e[n].get("stackedYCoords")[t]),[i,s]},_getStackedClosingPoints:function(){var e=this.get("order"),t=this.get("type"),n=this.get("graph"),r=this.get("direction"),i=n.seriesTypes[t],s,o,u=this.get("stackedXCoords"),a=this.get("stackedYCoords"),f,l,c,h,p,d,v,m,g,y,b,w;if(e<1)return this._getClosingPoints();l=i[e-1],p=l.get("stackedXCoords").concat(),d=l.get("stackedYCoords").concat(),r=="vertical"?(s=this._getFirstValidIndex(u),o=this._getLastValidIndex(u),c=l._getFirstValidIndex(p),h=l._getLastValidIndex(p)):(s=this._getFirstValidIndex(a),o=this._getLastValidIndex(a),c=l._getFirstValidIndex(d),h=l._getLastValidIndex(d)),h>=s&&c<=o?(c=Math.max(s,c),h=Math.min(o,h),p=p.slice(c,h+1),d=d.slice(c,h+1),f=c):f=o,m=[u[s]],g=[a[s]],y=s;while((isNaN(b)||b<e-1)&&y<=f)w=b,b=this._getHighestValidOrder(i,y,e,r),!isNaN(w)&&b>w&&(v=this._getCoordsByOrderAndIndex(i,y,w,r),m.push(v[0]),g.push(v[1])),v=this._getCoordsByOrderAndIndex(i,y,b,r),m.push(v[0]),g.push(v[1]),y+=1;p&&p.length>0&&h>s&&c<o&&(m=m.concat(p),g=g.concat(d),b=e-1),y=Math.max(s,h),e-=1,b=NaN;while(y<=o)w=b,b=this._getHighestValidOrder(i,y,e,r),isNaN(w)||(b>w?(v=this._getCoordsByOrderAndIndex(i,y,w,r),m.push(v[0]),g.push(v[1])):b<w&&(v=this._getCoordsByOrderAndIndex(i,y-1,b,r),m.push(v[0]),g.push(v[1]))),v=this._getCoordsByOrderAndIndex(i,y,b,r),m.push(v[0]),g.push(v[1]),y+=1;return m.reverse(),g.reverse(),[u.concat(m),a.concat(g)]},_getAreaDefaults:function(){return{}}},e.augment(k,e.Attribute),e.Fills=k,L.prototype={_plotDefaults:null,drawPlots:function(){if(!this.get("xcoords")||this.get("xcoords").length<1)return;var t=s.isNumber,n=e.clone(this.get("styles").marker),r=n.width,i=n.height,o=this.get("xcoords"),u=this.get("ycoords"),a=0,f=o.length,l=u[0],c,h,p=r/2,d=i/2,v,m,g=null,y=null,b=this.get("graphOrder"),w=this.get("groupMarkers");if(w){v=[],m=[];for(;a<f;++a)v.push(parseFloat(o[a]-p)),m.push(parseFloat(u[a]-d));this._createGroupMarker({xvalues:v,yvalues:m,fill:n.fill,border:n.border,dimensions:{width:r,height:i},graphOrder:b,shape:n.shape});return}s.isArray(n.fill.color)&&(g=n.fill.color.concat()),s.isArray(n.border.color)&&(y=n.border.color.concat()),this._createMarkerCache();for(;a<f;++a){l=parseFloat(u[a]-d),c=parseFloat(o[a]-p);if(!t(c)||!t(l)){this._markers.push(null);continue}g&&(n.fill.color=g[a%g.length]),y&&(n.border.color=y[a%y.length]),n.x=c,n.y=l,h=this.getMarker(n,b,a)}this._clearMarkerCache()},_groupShapes:{circle:e.CircleGroup,rect:e.RectGroup,ellipse:e.EllipseGroup,diamond:e.DiamondGroup},_getGroupShape:function(e){return s.isString(e)&&(e=this._groupShapes[e]),e},_getPlotDefaults:function(){var e={fill:{type:"solid",alpha:1,colors:null,alphas:null,ratios:null},border:{weight:1,alpha:1},width:10,height:10,shape:"circle"};return e.fill.color=this._getDefaultColor(this.get("graphOrder"),"fill"),e.border.color=this._getDefaultColor(this.get("graphOrder"),"border"),e},_markers:null,_markerCache:null,getMarker:function(e,t,n){var r,i=e.border;e.id=this.get("chart").get("id")+"_"+t+"_"+n,i.opacity=i.alpha,e.stroke=i,e.fill.opacity=e.fill.alpha;if(this._markerCache.length>0){while(!r){if(this._markerCache.length<1){r=this._createMarker(e,t,n);break}r=this._markerCache.shift()}r.set(e)}else r=this._createMarker(e,t,n);return this._markers.push(r),r},_createMarker:function(t,n,r){var i=this.get("graphic"),s,o=e.clone(t);return i.set("autoDraw",!1),o.type=o.shape,s=i.addShape(o),s.addClass(p),s},_createMarkerCache:function(){this._groupMarker&&(this._groupMarker.destroy(),this._groupMarker=null),this._markers&&this._markers.length>0?this._markerCache=this._markers.concat():this._markerCache=[],this._markers=[]},_createGroupMarker:function(e){var t,n=this.get("markers"),r=e.border,i,s,o;if(n&&n.length>0){while(n.length>0)t=n.shift(),t.destroy();this.set("markers",[])}r.opacity=r.alpha,s={id:this.get("chart").get("id")+"_"+e.graphOrder,stroke:r,fill:e.fill,dimensions:e.dimensions,xvalues:e.xvalues,yvalues:e.yvalues},s.fill.opacity=e.fill.alpha,o=this._getGroupShape(e.shape),o&&(s.type=o),e.hasOwnProperty("radius")&&!isNaN(e.radius)&&(s.dimensions.radius=e.radius),this._groupMarker&&this._groupMarker.destroy(),i=this.get("graphic"),this._groupMarker=i.addShape(s),i._redraw()},_toggleVisible:function(e){var t,n=this.get("markers"),r=0,i;if(n){i=n.length;for(;r<i;++r)t=n[r],t&&t.set("visible",e)}},_clearMarkerCache:function(){var e;while(this._markerCache.length>0)e=this._markerCache.shift(),e&&e.destroy()},updateMarkerState:function(t,n){if(this._markers&&this._markers[n]){var r,i,s=e.clone(this.get("styles").marker),o=this._getState(t),u=this.get("xcoords"),a=this.get("ycoords"),f=this._markers[n],l=o=="off"||!s[o]?s:s[o];l.fill.color=this._getItemColor(l.fill.color,n),l.border.color=this._getItemColor(l.border.color,n),l.stroke=l.border,f.set(l),r=l.width,i=l.height,f.set("x",u[n]-r/2),f.set("y",a[n]-i/2),f.set("visible",this.get("visible"))}},_getItemColor:function(e,t){return s.isArray(e)?e[t%e.length]:e},_setStyles:function(t){return t=this._parseMarkerStyles(t),e.Renderer.prototype._setStyles.apply(this,[t])},_parseMarkerStyles:function(e){if(e.marker){var t=this._getPlotDefaults();e.marker=this._mergeStyles(e.marker,t),e.marker.over&&(e.marker.over=this._mergeStyles(e.marker.over,e.marker)),e.marker.down&&(e.marker.down=this._mergeStyles(e.marker.down,e.marker))}return e},_getState:function(e){var t;switch(e){case"mouseout":t="off";break;case"mouseover":t="over";break;case"mouseup":t="over";break;case"mousedown":t="down"}return t},_stateSyles:null},e.augment(L,e.Attribute),e.Plots=L,A.prototype={drawSeries:function(){if(this.get("xcoords").length<1)return;var t=e.clone(this.get("styles").marker),n,r,i=this.get("xcoords"),o=this.get("ycoords"),u=0,a=i.length,f=o[0],l=this.get("type"),c=this.get("graph"),h=c.seriesTypes[l],p=h.length,d=0,v=0,m=0,g,y,b=this.get("order"),w=this.get("graphOrder"),E,S,x,T,N,C=null,k=null,L=[],A=[],O,M,_,D,P={width:[],height:[]},H=[],B=[],j=this.get("groupMarkers");s.isArray(t.fill.color)&&(C=t.fill.color.concat()),s.isArray(t.border.color)&&(k=t.border.color.concat()),this.get("direction")=="vertical"?(x="height",T="width"):(x="width",T="height"),n=t[x],r=t[T],this._createMarkerCache();for(;u<p;++u)y=h[u],d+=y.get("styles").marker[x],b>u&&(m=d);v=a*d,this._maxSize=c.get(x),v>this._maxSize&&(g=c.get(x)/v,d*=g,m*=g,n*=g,n=Math.max(n,1),this._maxSize=n),m-=d/2;for(u=0;u<a;++u){O=i[u]-d/2,M=O+d,_=o[u]-d/2,D=_+d,L.push({start:O,end:M}),A.push({start:_,end:D});if(isNaN(i[u])||isNaN(o[u])){this._markers.push(null);continue}N=this._getMarkerDimensions(i[u],o[u],r,m),!isNaN(N.calculatedSize)&&N.calculatedSize>0?(f=N.top,E=N.left,j?(P[x][u]=n,P[T][u]=N.calculatedSize,H.push(E),B.push(f)):(t[x]=n,t[T]=N.calculatedSize,t.x=E,t.y=f,C&&(t.fill.color=C[u%C.length]),k&&(t.border.color=k[u%k.length]),S=this.getMarker(t,w,u))):j||this._markers.push(null)}this.set("xMarkerPlane",L),this.set("yMarkerPlane",A),j?this._createGroupMarker({fill:t.fill,border:t.border,dimensions:P,xvalues:H,yvalues:B,shape:t.shape}):this._clearMarkerCache()},_defaultFillColors:["#66007f","#a86f41","#295454","#996ab2","#e8cdb7","#90bdbd","#000000","#c3b8ca","#968373","#678585"],_getPlotDefaults:function(){var e={fill:{type:"solid",alpha:1,colors:null,alphas:null,ratios:null},border:{weight:0,alpha:1},width:12,height:12,shape:"rect",padding:{top:0,left:0,right:0,bottom:0}};return e.fill.color=this._getDefaultColor(this.get("graphOrder"),"fill"),e.border.color=this._getDefaultColor(this.get("graphOrder"),"border"),e}},e.Histogram=A,e.CartesianSeries=e.Base.create("cartesianSeries",e.Base,[e.Renderer],{_xDisplayName:null,_yDisplayName:null,_leftOrigin:null,_bottomOrigin:null,render:function(){this._setCanvas(),this.addListeners(),this.set("rendered",!0),this.validate()},addListeners:function(){var t=this.get("xAxis"),n=this.get("yAxis");t&&(this._xDataReadyHandle=t.after("dataReady",e.bind(this._xDataChangeHandler,this)),this._xDataUpdateHandle=t.after("dataUpdate",e.bind(this._xDataChangeHandler,this))),n&&(this._yDataReadyHandle=n.after("dataReady",e.bind(this._yDataChangeHandler,this)),this._yDataUpdateHandle=n.after("dataUpdate",e.bind(this._yDataChangeHandler,this))),this._xAxisChangeHandle=this.after("xAxisChange",this._xAxisChangeHandler),this._yAxisChangeHandle=this.after("yAxisChange",this._yAxisChangeHandler),this._stylesChangeHandle=this.after("stylesChange",function(e){var t=this._updateAxisData();t&&this.draw()}),this._widthChangeHandle=this.after("widthChange",function(e){var t=this._updateAxisData();t&&this.draw()}),this._heightChangeHandle=this.after("heightChange",function(e){var t=this._updateAxisData();t&&this.draw()}),this._visibleChangeHandle=this.after("visibleChange",this._handleVisibleChange)},_xAxisChangeHandler:function(t){var n=this.get("xAxis");n.after("dataReady",e.bind(this._xDataChangeHandler,this)),n.after("dataUpdate",e.bind(this._xDataChangeHandler,this))},_yAxisChangeHandler:function(t){var n=this.get("yAxis");n.after("dataReady",e.bind(this._yDataChangeHandler,this)),n.after("dataUpdate",e.bind(this._yDataChangeHandler,this))},GUID:"yuicartesianseries",_xDataChangeHandler:function(e){var t=this._updateAxisData();t&&this.draw()},_yDataChangeHandler:function(e){var t=this._updateAxisData();t&&this.draw()},_updateAxisData:function(){var e=this.get("xAxis"),t=this.get("yAxis"),n=this.get("xKey"),r=this.get("yKey"),i,s;return!e||!t||!n||!r?!1:(s=e.getDataByKey(n),i=t.getDataByKey(r),!s||!i?!1:(this.set("xData",s.concat()),this.set("yData",i.concat()),!0))},validate:function(){this.get("xData")&&this.get("yData")||this._updateAxisData()?this.draw():this.fire("drawingComplete")},_setCanvas:function(){var e=this.get("graph"),t=e.get("graphic");this.set("graphic",t)},setAreaData:function(){var e=s.isNumber,t,n,r=this.get("graph"),i=r.get("width"),o=r.get("height"),u=this.get("xAxis"),a=this.get("yAxis"),f=this.get("xData").concat(),l=this.get("yData").concat(),c,h,p=u.getEdgeOffset(f.length,i),d=a.getEdgeOffset(l.length,o),v=this.get("styles").padding,m=v.left,g=v.top,y=i-(m+v.right+p),b=o-(g+v.bottom+d),w=[],E=[],S=u.get("maximum"),x=u.get("minimum"),T=a.get("maximum"),N=a.get("minimum"),C=y/(S-x),k=b/(T-N),L,A=this.get("direction"),O=0,M=[],_=[],D=this.get("xMarkerPlaneOffset"),P=this.get("yMarkerPlaneOffset"),H=this.get("graphic");H.set("width",i),H.set("height",o),L=f.length,p*=.5,d*=.5,A==="vertical"&&(l=l.reverse()),this._leftOrigin=Math.round((0-x)*C+m+p),this._bottomOrigin=Math.round(b+g+d),N<0&&(this._bottomOrigin=this._bottomOrigin-(0-N)*k);for(;O<L;++O)c=parseFloat(f[O]),h=parseFloat(l[O]),e(c)?t=(c-x)*C+m+p:t=NaN,e(h)?n=b+g+d-(h-N)*k:n=NaN,w.push(t),E.push(n),M.push({start:t-D,end:t+D}),_.push({start:n-P,end:n+P});this.set("xcoords",w),this.set("ycoords",E),this.set("xMarkerPlane",M),this.set("yMarkerPlane",_),this._dataLength=L},_getFirstValidIndex:function(e){var t,n=-1,r=e.length;while(!s.isNumber(t)&&n<r)n+=1,t=e[n];return n},_getLastValidIndex:function(e){var t,n=e.length,r=-1;while(!s.isNumber(t)&&n>r)n-=1,t=e[n];return n},draw:function(){var e=this.get("graph"),t=e.get("width"),n=e.get("height");if(this.get("rendered")&&isFinite(t)&&isFinite(n)&&t>0&&n>0&&(this.get("xData")&&this.get("yData")||this._updateAxisData())){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1,this.setAreaData(),this.get("xcoords")&&this.get("ycoords")&&this.drawSeries(),this._drawing=!1,this._callLater?this.draw():(this._toggleVisible(this.get("visible")),this.fire("drawingComplete"))}},_defaultPlaneOffset:4,_getDefaultStyles:function(){return{padding:{top:0,left:0,right:0,bottom:0}}},_defaultLineColors:["#426ab3","#d09b2c","#000000","#b82837","#b384b5","#ff7200","#779de3","#cbc8ba","#7ed7a6","#007a6c"],_defaultFillColors:["#6084d0","#eeb647","#6c6b5f","#d6484f","#ce9ed1","#ff9f3b","#93b7ff","#e0ddd0","#94ecba","#309687"],_defaultBorderColors:["#205096","#b38206","#000000","#94001e","#9d6fa0","#e55b00","#5e85c9","#adab9e","#6ac291","#006457"],_defaultSliceColors:["#66007f","#a86f41","#295454","#996ab2","#e8cdb7","#90bdbd","#000000","#c3b8ca","#968373","#678585"],_getDefaultColor:function(e,t){var n={line:this._defaultLineColors,fill:this._defaultFillColors,border:this._defaultBorderColors,slice:this._defaultSliceColors},r=n[t],i=r.length;return e=e||0,e>=i&&(e%=i),t=t||"fill",n[t][e]},_handleVisibleChange:function(e){this._toggleVisible(this.get("visible"))},getTotalValues:function(){var e=this.get("valueAxis").getTotalByKey(this.get("valueKey"));return e},destructor:function(){var t,n=this.get("markers");this.get("rendered")&&(this._xDataReadyHandle&&this._xDataReadyHandle.detach(),this._xDataUpdateHandle&&this._xDataUpdateHandle.detach(),this._yDataReadyHandle&&this._yDataReadyHandle.detach(),this._yDataUpdateHandle&&this._yDataUpdateHandle.detach(),this._xAxisChangeHandle.detach(),this._yAxisChangeHandle.detach(),this._stylesChangeHandle.detach(),this._widthChangeHandle.detach(),this._heightChangeHandle.detach(),this._visibleChangeHandle.detach());while(n&&n.length>0)t=n.shift(),t&&t instanceof e.Shape&&t.destroy();this._path&&(this._path.destroy(),this._path=null),this._lineGraphic&&(this._lineGraphic.destroy(),this._lineGraphic=null),this._groupMarker&&(this._groupMarker.destroy(),this._groupMarker=null)}},{ATTRS:{xDisplayName:{getter:function(){return this._xDisplayName||this.get("xKey")},setter:function(e){return this._xDisplayName=e.toString(),e}},yDisplayName:{getter:function(){return this._yDisplayName||this.get("yKey")},setter:function(e){return this._yDisplayName=e.toString(),e}},categoryDisplayName:{lazyAdd:!1,getter:function(){return this.get("direction")=="vertical"?this.get("yDisplayName"):this.get("xDisplayName")},setter:function(e){return this.get("direction")=="vertical"?this._yDisplayName=e:this._xDisplayName=e,e}},valueDisplayName:{lazyAdd:!1,getter:function(){return this.get("direction")=="vertical"?this.get("xDisplayName"):this.get("yDisplayName")},setter:function(e){return this.get("direction")=="vertical"?this._xDisplayName=e:this._yDisplayName=e,e}},type:{value:"cartesian"},order:{},graphOrder:{},xcoords:{},ycoords:{},chart:{readOnly:!0,getter:function(){return this.get("graph").get("chart")}},graph:{},xAxis:{},yAxis:{},xKey:{setter:function(e){return e.toString()}},yKey:{setter:function(e){return e.toString()}},xData:{},yData:{},rendered:{value:!1},width:{readOnly:!0,getter:function(){this.get("graph").get("width")}},height:{readOnly:!0,getter:function(){this.get("graph").get("height")}},visible:{value:!0},xMarkerPlane:{},yMarkerPlane:{},xMarkerPlaneOffset:{getter:function(){var e=this.get("styles").marker;return e&&e.width&&isFinite(e.width)?e.width*.5:this._defaultPlaneOffset}},yMarkerPlaneOffset:{getter:function(){var e=this.get("styles").marker;return e&&e.height&&isFinite(e.height)?e.height*.5:this._defaultPlaneOffset}},direction:{value:"horizontal"},groupMarkers:{getter:function(){return this._groupMarkers===undefined?this.get("graph").get("groupMarkers"):this._groupMarkers},setter:function(e){return this._groupMarkers=e,e}}}}),e.MarkerSeries=e.Base.create("markerSeries",e.CartesianSeries,[e.Plots],{drawSeries:function(){this.drawPlots()},_setStyles:function(t){return t.marker||(t={marker:t}),t=this._parseMarkerStyles(t),e.MarkerSeries.superclass._mergeStyles.apply(this,[t,this._getDefaultStyles()])},_getDefaultStyles:function(){var t=this._mergeStyles({marker:this._getPlotDefaults()},e.MarkerSeries.superclass._getDefaultStyles());return t}},{ATTRS:{type:{value:"marker"}}}),e.LineSeries=e.Base.create("lineSeries",e.CartesianSeries,[e.Lines],{drawSeries:function(){this.drawLines()},_setStyles:function(t){return t.line||(t={line:t}),e.LineSeries.superclass._setStyles.apply(this,[t])},_getDefaultStyles:function(){var t=this._mergeStyles({line:this._getLineDefaults()},e.LineSeries.superclass._getDefaultStyles());return t}},{ATTRS:{type:{value:"line"}}}),e.SplineSeries=e.Base.create("splineSeries",e.LineSeries,[e.CurveUtil,e.Lines],{drawSeries:function(){this.drawSpline()}},{ATTRS:{type:{value:"spline"}}}),e.StackedSplineSeries=e.Base.create("stackedSplineSeries",e.SplineSeries,[e.StackingUtil],{setAreaData:function(){e.StackedSplineSeries.superclass.setAreaData.apply(this),this._stackCoordinates.apply(this)}},{ATTRS:{type:{value:"stackedSpline"}}}),e.StackedMarkerSeries=e.Base.create("stackedMarkerSeries",e.MarkerSeries,[e.StackingUtil],{setAreaData:function(){e.StackedMarkerSeries.superclass.setAreaData.apply(this),this._stackCoordinates.apply(this)}},{ATTRS:{type:{value:"stackedMarker"}}}),e.ColumnSeries=e.Base.create("columnSeries",e.MarkerSeries,[e.Histogram],{_getMarkerDimensions:function(e,t,n,r){var i={left:e+r};return this._bottomOrigin>=t?(i.top=t,i.calculatedSize=this._bottomOrigin-i.top):(i.top=this._bottomOrigin,i.calculatedSize=t-this._bottomOrigin),i},updateMarkerState:function(t,n){if(this._markers&&this._markers[n]){var r=e.clone(this.get("styles").marker),i,s=this._getState(t),o=this.get("xcoords"),u=this.get("ycoords"),a=this._markers[n],f,l=this.get("graph"),c,h=l.seriesTypes[this.get("type")],p=h.length,d=0,v=0,m,g=0,y=[],b=this.get("order"),w;i=s=="off"||!r[s]?e.clone(r):e.clone(r[s]),i.fill.color=this._getItemColor(i.fill.color,n),i.border.color=this._getItemColor(i.border.color,n),w=this._getMarkerDimensions(o[n],u[n],r.width,v),i.height=w.calculatedSize,i.width=Math.min(this._maxSize,i.width),a.set(i);for(;g<p;++g)y[g]=o[n]+d,c=h[g].get("styles").marker,d+=Math.min(this._maxSize,c.width),b>g&&(v=d),v-=d/2;for(g=0;g<p;++g)f=h[g].get("markers"),f&&(m=f[n],m&&m!==undefined&&m.set("x",y[g]-d/2))}}},{ATTRS:{type:{value:"column"}}}),e.BarSeries=e.Base.create("barSeries",e.MarkerSeries,[e.Histogram],{_getMarkerDimensions:function(e,t,n,r){var i={top:t+r};return e>=this._leftOrigin?(i.left=this._leftOrigin,i.calculatedSize=e-i.left):(i.left=e,i.calculatedSize=this._leftOrigin-e),i},updateMarkerState:function(t,n){if(this._markers&&this._markers[n]){var r=e.clone(this.get("styles").marker),i,s=this._getState(t),o=this.get("xcoords"),u=this.get("ycoords"),a=this._markers[n],f,l=this.get("graph"),c=l.seriesTypes[this.get("type")],h=c.length,p,d=0,v=0,m,g=0,y=[],b=this.get("order"),w;i=s=="off"||!r[s]?r:r[s],i.fill.color=this._getItemColor(i.fill.color,n),i.border.color=this._getItemColor(i.border.color,n),w=this._getMarkerDimensions(o[n],u[n],r.height,v),i.width=w.calculatedSize,i.height=Math.min(this._maxSize,i.height),a.set(i);for(;g<h;++g)y[g]=u[n]+d,p=c[g].get("styles").marker,d+=Math.min(this._maxSize,p.height),b>g&&(v=d),v-=d/2;for(g=0;g<h;++g)f=c[g].get("markers"),f&&(m=f[n],m&&m!==undefined&&m.set("y",y[g]-d/2))}}},{ATTRS:{type:{value:"bar"},direction:{value:"vertical"}}}),e.AreaSeries=e.Base.create("areaSeries",e.CartesianSeries,[e.Fills],{drawSeries:function(){this.drawFill.apply(this,this._getClosingPoints())},_setStyles:function(t){return t.area||(t={area:t}),e.AreaSeries.superclass._setStyles.apply(this,[t])},_getDefaultStyles:function(){var t=this._mergeStyles({area:this._getAreaDefaults()},e.AreaSeries.superclass._getDefaultStyles());return t}},{ATTRS:{type:{value:"area"}}}),e.AreaSplineSeries=e.Base.create("areaSplineSeries",e.AreaSeries,[e.CurveUtil],{drawSeries:function(){this.drawAreaSpline()}},{ATTRS:{type:{value:"areaSpline"}}}),e.StackedAreaSplineSeries=e.Base.create("stackedAreaSplineSeries",e.AreaSeries,[e.CurveUtil,e.StackingUtil],{drawSeries:function(){this._stackCoordinates(),this.drawStackedAreaSpline()}},{ATTRS:{type:{value:"stackedAreaSpline"}}}),e.ComboSeries=e.Base.create("comboSeries",e.CartesianSeries,[e.Fills,e.Lines,e.Plots],{drawSeries:function(){this.get("showAreaFill")&&this.drawFill.apply(this,this._getClosingPoints()),this.get("showLines")&&this.drawLines(),this.get("showMarkers")&&this.drawPlots()},_toggleVisible:function(e){var t,n,r,i;this.get("showAreaFill")&&this._path&&this._path.set("visible",e),this.get("showLines")&&this._lineGraphic&&this._lineGraphic.set("visible",e);if(this.get("showMarkers")){t=this.get("markers");if(t){i=0,r=t.length;for(;i<r;++i)n=t[i],n&&n.set("visible",e)}}},_getDefaultStyles:function(){var t=e.ComboSeries.superclass._getDefaultStyles();return t.line=this._getLineDefaults(),t.marker=this._getPlotDefaults(),t.area=this._getAreaDefaults(),t}},{ATTRS:{type:{value:"combo"},showAreaFill:{value:!1},showLines:{value:!0},showMarkers:{value:!0},marker:{lazyAdd:!1,getter:function(){return this.get("styles").marker},setter:function(e){this.set("styles",{marker:e})}},line:{lazyAdd:!1,getter:function(){return this.get("styles").line},setter:function(e){this.set("styles",{line:e})}},area:{lazyAdd:!1,getter:function(){return this.get("styles").area},setter:function(e){this.set("styles",{area:e})}}}}),e.StackedComboSeries=e.Base.create("stackedComboSeries",e.ComboSeries,[e.StackingUtil],{setAreaData:function(){e.StackedComboSeries.superclass.setAreaData.apply(this),this._stackCoordinates.apply(this)},drawSeries:function(){this.get("showAreaFill")&&this.drawFill.apply(this,this._getStackedClosingPoints()),this.get("showLines")&&this.drawLines(),this.get("showMarkers")&&this.drawPlots()}},{ATTRS:{type:{value:"stackedCombo"},showAreaFill:{value:!0}}}),e.ComboSplineSeries=e.Base.create("comboSplineSeries",e.ComboSeries,[e.CurveUtil],{drawSeries:function(){this.get("showAreaFill")&&this.drawAreaSpline(),this.get("showLines")&&this.drawSpline(),this.get("showMarkers")&&this.drawPlots()}},{ATTRS:{type:{value:"comboSpline"}}}),e.StackedComboSplineSeries=e.Base.create("stackedComboSplineSeries",e.StackedComboSeries,[e.CurveUtil],{drawSeries:function(){this.get("showAreaFill")&&this.drawStackedAreaSpline(),this.get("showLines")&&this.drawSpline(),this.get("showMarkers")&&this.drawPlots()}},{ATTRS:{type:{value:"stackedComboSpline"},showAreaFill:{value:!0}}}),e.StackedLineSeries=e.Base.create("stackedLineSeries",e.LineSeries,[e.StackingUtil],{setAreaData:function(){e.StackedLineSeries.superclass.setAreaData.apply(this),this._stackCoordinates.apply(this)}},{ATTRS:{type:{value:"stackedLine"}}}),e.StackedAreaSeries=e.Base.create("stackedAreaSeries",e.AreaSeries,[e.StackingUtil],{setAreaData:function(){e.StackedAreaSeries.superclass.setAreaData.apply(this),this._stackCoordinates.apply(this)},drawSeries:function(){this.drawFill.apply(this,this._getStackedClosingPoints())}},{ATTRS:{type:{value:"stackedArea"}}}),e.StackedColumnSeries=e.Base.create("stackedColumnSeries",e.ColumnSeries,[e.StackingUtil],{drawSeries:function(){if(this.get("xcoords").length<1)return;var t=s.isNumber,n=e.clone(this.get("styles").marker),r=n.width,i=n.height,o=this.get("xcoords"),u=this.get("ycoords"),a=0,f=o.length,l=u[0],c=this.get("type"),h=this.get("graph"),p=h.seriesTypes[c],d,v=this.get("order"),m=this.get("graphOrder"),g,y,b,w,E,S,x,T=v===0,N=f*r,C={width:[],height:[]},k=[],L=[],A=this.get("groupMarkers");s.isArray(n.fill.color)&&(b=n.fill.color.concat()),s.isArray(n.border.color)&&(w=n.border.color.concat()),this._createMarkerCache(),N>this.get("width")&&(d=this.width/N,r*=d,r=Math.max(r,1));if(!T){E=p[v-1],S=E.get("negativeBaseValues"),x=E.get("positiveBaseValues");if(!S||!x)T=!0,x=[],S=[]}else S=[],x=[];this.set("negativeBaseValues",S),this.set("positiveBaseValues",x);for(a=0;a<f;++a){g=o[a],l=u[a];if(!t(l)||!t(g)){T&&(S[a]=this._bottomOrigin,x[a]=this._bottomOrigin),this._markers.push(null);continue}T?(i=Math.abs(this._bottomOrigin-l),l<this._bottomOrigin?(x[a]=l,S[a]=this._bottomOrigin):l>this._bottomOrigin?(x[a]=this._bottomOrigin,S[a]=l,l-=i):(x[a]=l,S[a]=l)):l>this._bottomOrigin?(l+=S[a]-this._bottomOrigin,i=l-S[a],S[a]=l,l-=i):l<=this._bottomOrigin&&(l=x[a]-(this._bottomOrigin-l),i=x[a]-l,x[a]=l),!isNaN(i)&&i>0?(g-=r/2,A?(C.width[a]=r,C.height[a]=i,k.push(g),L.push(l)):(n.width=r,n.height=i,n.x=g,n.y=l,b&&(n.fill.color=b[a%b.length]),w&&(n.border.color=w[a%w.length]),y=this.getMarker(n,m,a))):A||this._markers.push(null)}A?this._createGroupMarker({fill:n.fill,border:n.border,dimensions:C,xvalues:k,yvalues:L,shape:n.shape}):this._clearMarkerCache()},updateMarkerState:function(t,n){if(this._markers&&this._markers[n]){var r,i,o=this._getState(t),u=this.get("xcoords"),a=this._markers[n],f=0,l,c;r=this.get("styles").marker,f=r.width*.5,i=o=="off"||!r[o]?e.clone(r):e.clone(r[o]),i.height=a.get("height"),i.x=u[n]-f,i.y=a.get("y"),i.id=a.get("id"),l=i.fill.color,c=i.border.color,s.isArray(l)?i.fill.color=l[n%l.length]:i.fill.color=this._getItemColor(i.fill.color,n),s.isArray(c)?i.border.color=c[n%c.length]:i.border.color=this._getItemColor(i.border.color,n),a.set(i)}},_getPlotDefaults:function(){var e={fill:{type:"solid",alpha:1,colors:null,alphas:null,ratios:null},border:{weight:0,alpha:1},width:24,height:24,shape:"rect",padding:{top:0,left:0,right:0,bottom:0}};return e.fill.color=this._getDefaultColor(this.get("graphOrder"),"fill"),e.border.color=this._getDefaultColor(this.get("graphOrder"),"border"),e}},{ATTRS:{type:{value:"stackedColumn"},negativeBaseValues:{value:null},positiveBaseValues:{value:null}}}),e.StackedBarSeries=e.Base.create("stackedBarSeries",e.BarSeries,[e.StackingUtil],{drawSeries:function(){if(this.get("xcoords").length<1)return;var t=s.isNumber,n=e.clone(this.get("styles").marker),r=n.width,i=n.height,o=this.get("xcoords"),u=this.get("ycoords"),a=0,f=o.length,l=u[0],c=this.get("type"),h=this.get("graph"),p=h.seriesTypes[c],d,v=this.get("order"),m=this.get("graphOrder"),g,y,b,w,E,S,x,T=v===0,N=f*i,C={width:[],height:[]},k=[],L=[],A=this.get("groupMarkers");s.isArray(n.fill.color)&&(S=n.fill.color.concat()),s.isArray(n.border.color)&&(x=n.border.color.concat()),this._createMarkerCache(),N>this.get("height")&&(d=this.height/N,i*=d,i=Math.max(i,1));if(!T){b=p[v-1],w=b.get("negativeBaseValues"),E=b.get("positiveBaseValues");if(!w||!E)T=!0,E=[],w=[]}else w=[],E=[];this.set("negativeBaseValues",w),this.set("positiveBaseValues",E);for(a=0;a<f;++a){l=u[a],g=o[a];if(!t(l)||!t(g)){T&&(E[a]=this._leftOrigin,w[a]=this._leftOrigin),this._markers.push(null);continue}T?(r=Math.abs(g-this._leftOrigin),g>this._leftOrigin?(E[a]=g,w[a]=this._leftOrigin,g-=r):g<this._leftOrigin?(E[a]=this._leftOrigin,w[a]=g):(E[a]=g,w[a]=this._leftOrigin)):g<this._leftOrigin?(g=w[a]-(this._leftOrigin-o[a]),r=w[a]-g,w[a]=g):g>=this._leftOrigin&&(g+=E[a]-this._leftOrigin,r=g-E[a],E[a]=g,g-=r),!isNaN(r)&&r>0?(l-=i/2,A?(C.width[a]=r,C.height[a]=i,k.push(g),L.push(l)):(n.width=r,n.height=i,n.x=g,n.y=l,S&&(n.fill.color=S[a%S.length]),x&&(n.border.color=x[a%x.length]),y=this.getMarker(n,m,a))):A||this._markers.push(null)}A?this._createGroupMarker({fill:n.fill,border:n.border,dimensions:C,xvalues:k,yvalues:L,shape:n.shape}):this._clearMarkerCache()},updateMarkerState:function(t,n){if(this._markers[n]){var r=this._getState(t),i=this.get("ycoords"),o=this._markers[n],u=this.get("styles").marker,a=u.height,f=r=="off"||!u[r]?e.clone(u):e.clone(u[r]),l,c;f.y=i[n]-a/2,f.x=o.get("x"),f.width=o.get("width"),f.id=o.get("id"),l=f.fill.color,c=f.border.color,s.isArray(l)?f.fill.color=l[n%l.length]:f.fill.color=this._getItemColor(f.fill.color,n),s.isArray(c)?f.border.color=c[n%c.length]:f.border.color=this._getItemColor(f.border.color,n),o.set(f)}},_getPlotDefaults:function(){var e={fill:{type:"solid",alpha:1,colors:null,alphas:null,ratios:null},border:{weight:0,alpha:1},width:24,height:24,shape:"rect",padding:{top:0,left:0,right:0,bottom:0}};return e.fill.color=this._getDefaultColor(this.get("graphOrder"),"fill"),e.border.color=this._getDefaultColor(this.get("graphOrder"),"border"),e}},{ATTRS:{type:{value:"stackedBar"},direction:{value:"vertical"},negativeBaseValues:{value:null},positiveBaseValues:{value:null}}}),e.PieSeries=e.Base.create("pieSeries",e.MarkerSeries,[],{_map:null,_image:null,_setMap:function(){var e="pieHotSpotMapi_"+Math.round(1e5*Math.random()),t=this.get("graph").get("contentBox"),n;if(this._image){t.removeChild(this._image);while(this._areaNodes&&this._areaNodes.length>0)n=this._areaNodes.shift(),this._map.removeChild(n);t.removeChild(this._map)}this._image=i.createElement("img"),this._image.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==",t.appendChild(this._image),this._image.setAttribute("usemap","#"+e),this._image.style.zIndex=3,this._image.style.opacity=0,this._image.setAttribute("alt","imagemap"),this._map=i.createElement("map"),this._map.style.zIndex=5,t.appendChild(this._map),this._map.setAttribute("name",e),this._map.setAttribute("id",e),this._areaNodes=[]},_categoryDisplayName:null,_valueDisplayName:null,addListeners:function(){var t=this.get("categoryAxis"),n=this.get("valueAxis");t&&(t.after("dataReady",e.bind(this._categoryDataChangeHandler,this)),t.after("dataUpdate",e.bind(this._categoryDataChangeHandler,this))),n&&(n.after("dataReady",e.bind(this._valueDataChangeHandler,this)),n.after("dataUpdate",e.bind(this._valueDataChangeHandler,this))),this.after("categoryAxisChange",this.categoryAxisChangeHandler),this.after("valueAxisChange",this.valueAxisChangeHandler),this.after("stylesChange",this._updateHandler)},validate:function(){this.draw(),this._renderered=!0},_categoryAxisChangeHandler:function(t){var n=this.get("categoryAxis");n.after("dataReady",e.bind(this._categoryDataChangeHandler,this)),n.after("dataUpdate",e.bind(this._categoryDataChangeHandler,this))},_valueAxisChangeHandler:function(t){var n=this.get("valueAxis");n.after("dataReady",e.bind(this._valueDataChangeHandler,this)),n.after("dataUpdate",e.bind(this._valueDataChangeHandler,this))},GUID:"pieseries",_categoryDataChangeHandler:function(e){this._rendered&&this.get("categoryKey")&&this.get("valueKey")&&this.draw()},_valueDataChangeHandler:function(e){this._rendered&&this.get("categoryKey")&&this.get("valueKey")&&this.draw()},draw:function(){var e=this.get("graph"),t=e.get("width"),n=e.get("height");if(isFinite(t)&&isFinite(n)&&t>0&&n>0){this._rendered=!0;if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1,this.drawSeries(),this._drawing=!1,this._callLater?this.draw():this.fire("drawingComplete")}},drawPlots:function(){var t=this.get("valueAxis").getDataByKey(this.get("valueKey")).concat(),n=this.get("categoryAxis").getDataByKey(this.get("categoryKey")).concat(),r=0,i=t.length,s=this.get("styles").marker,o=s.fill.colors,u=s.fill.alphas||["1"],a=s.border.colors,f=[s.border.weight],l=[s.border.alpha],c=f.concat(),h=a.concat(),p=l.concat(),d,v,m=s.padding,g=this.get("graph"),y=Math.min(g.get("width"),g.get("height")),b=y-(m.left+m.right),w=y-(m.top+m.bottom),E=-90,S=b/2,x=w/2,T=Math.min(S,x),N=0,C,k=0,L,A,O,M,_,D=this.get("graphOrder"),P=e.Graphic.NAME=="canvasGraphic";for(;N<i;++N)C=parseFloat(t[N]),t.push(C),isNaN(C)||(r+=C);d=o?o.concat():null,v=u?u.concat():null,this._createMarkerCache(),P&&(this._setMap(),this._image.width=b,this._image.height=w);for(N=0;N<i;N++)C=t[N],r===0?k=360/t.length:k=360*(C/r),d&&d.length<1&&(d=o.concat()),v&&v.length<1&&(v=u.concat()),c&&c.length<1&&(c=f.concat()),c&&h.length<1&&(h=a.concat()),p&&p.length<1&&(p=l.concat()),O=c?c.shift():null,L=h?h.shift():null,A=p?p.shift():null,E+=k,M={border:{color:L,weight:O,alpha:A},fill:{color:d?d.shift():this._getDefaultColor(N,"slice"),alpha:v?v.shift():null},type:"pieslice",arc:k,radius:T,startAngle:E,cx:S,cy:x,width:b,height:w},_=this.getMarker(M,D,N),P&&this._addHotspot(M,D,N);this._clearMarkerCache()},_addHotspot:function(e,t,n){var r=i.createElement("area"),s=1,o=e.cx,u=e.cy,a=e.arc,f=e.startAngle-a,l=e.startAngle,c=e.radius,h=o+Math.cos(f/180*Math.PI)*c,d=u+Math.sin(f/180*Math.PI)*c,v=o+Math.cos(l/180*Math.PI)*c,m=u+Math.sin(l/180*Math.PI)*c,g=Math.floor(a/10)-1,y=a/Math.floor(a/10)/180*Math.PI,b=Math.atan((d-u)/(h-o)),w=o+", "+u+", "+h+", "+d,E,S,x;for(s=1;s<=g;++s)x=y*s,E=Math.cos(b+x),S=Math.sin(b+x),f<=90?(w+=", "+(o+c*Math.cos(b+y*s)),w+=", "+(u+c*Math.sin(b+y*s))):(w+=", "+(o-c*Math.cos(b+y*s)),w+=", "+(u-c*Math.sin(b+y*s)));w+=", "+v+", "+m,w+=", "+o+", "+u,this._map.appendChild(r),r.setAttribute("class",p),r.setAttribute("id","hotSpot_"+t+"_"+n),r.setAttribute("shape","polygon"),r.setAttribute("coords",w),this._areaNodes.push(r)},updateMarkerState:function(e,t){if(this._markers[t]){var n=this._getState(e),r,i,s=this._markers[t],o=this.get("styles").marker;r=n=="off"||!o[n]?o:o[n],i=this._mergeStyles(r,{}),i.fill.color=i.fill.colors[t%i.fill.colors.length],i.fill.alpha=i.fill.alphas[t%i.fill.alphas.length],s.set(i)}},_createMarker:function(t,n,r){var i=this.get("graphic"),s,o=e.clone(t);return i.set("autoDraw",!1),s=i.addShape(o),s.addClass(p),s},_clearMarkerCache:function(){var e=this._markerCache.length,t=0,n;for(;t<e;++t)n=this._markerCache[t],n&&n.destroy();this._markerCache=[]},_getPlotDefaults:function(){var e={padding:{top:0,left:0,right:0,bottom:0},fill:{alphas:["1"]},border:{weight:0,alpha:1}};return e.fill.colors=this._defaultSliceColors,e.border.colors=this._defaultBorderColors,e},_defaultLineColors:["#426ab3","#d09b2c","#000000","#b82837","#b384b5","#ff7200","#779de3","#cbc8ba","#7ed7a6","#007a6c"],_defaultFillColors:["#6084d0","#eeb647","#6c6b5f","#d6484f","#ce9ed1","#ff9f3b","#93b7ff","#e0ddd0","#94ecba","#309687"],_defaultBorderColors:["#205096","#b38206","#000000","#94001e","#9d6fa0","#e55b00","#5e85c9","#adab9e","#6ac291","#006457"],_defaultSliceColors:["#66007f","#a86f41","#295454","#996ab2","#e8cdb7","#90bdbd","#000000","#c3b8ca","#968373","#678585"],_getDefaultColor:function(e,t){var n={line:this._defaultLineColors,fill:this._defaultFillColors,border:this._defaultBorderColors,slice:this._defaultSliceColors},r=n[t],i=r.length;return e=e||0,e>=i&&(e%=i),t=t||"fill",n[t][e]}},{ATTRS:{type:{value:"pie"},order:{},graph:{},categoryAxis:{value:null,validator:function(e){return e!==this.get("categoryAxis")}},valueAxis:{value:null,validator:function(e){return e!==this.get("valueAxis")}},categoryKey:{value:null,validator:function(e){return e!==this.get("categoryKey")}},valueKey:{value:null,validator:function(e){return e!==this.get("valueKey")}},categoryDisplayName:{setter:function(e){return this._categoryDisplayName=e,e},getter:function(){return this._categoryDisplayName||this.get("categoryKey")}},valueDisplayName:{setter:function(e){return this._valueDisplayName=e,e},getter:function(){return this._valueDisplayName||this.get("valueKey")}},slices:null}}),e.Gridlines=e.Base.create("gridlines",e.Base,[e.Renderer],{_path:null,remove:function(){var e=this._path;e&&e.destroy()},draw:function(){this.get("axis")&&this.get("graph")&&this._drawGridlines()},_drawGridlines:function(){var e,t=this.get("axis"),n=t.get("position"),r,i=0,s,o=this.get("direction"),u=this.get("graph"),a=u.get("width"),f=u.get("height"),l=this.get("styles").line,c=l.color,h=l.weight,p=l.alpha,d=o=="vertical"?this._verticalLine:this._horizontalLine;if(isFinite(a)&&isFinite(f)&&a>0&&f>0){if(n!="none"&&t&&t.get("tickPoints"))r=t.get("tickPoints"),s=r.length;else{r=[],s=t.get("styles").majorUnit.count;for(;i<s;++i)r[i]={x:a*(i/(s-1)),y:f*(i/(s-1))};i=0}e=u.get("gridlines"),e.set("width",a),e.set("height",f),e.set("stroke",{weight:h,color:c,opacity:p});for(;i<s;++i)d(e,r[i],a,f);e.end()}},_horizontalLine:function(e,t,n,r){e.moveTo(0,t.y),e.lineTo(n,t.y)},_verticalLine:function(e,t,n,r){e.moveTo(t.x,0),e.lineTo(t.x,r)},_getDefaultStyles:function(){var e={line:{color:"#f0efe9",weight:1,alpha:1}};return e}},{ATTRS:{direction:{},axis:{},graph:{}}}),e.Graph=e.Base.create("graph",e.Widget,[e.Renderer],{bindUI:function(){var e=this.get("boundingBox");e.setStyle("position","absolute"),this.after("widthChange",this._sizeChangeHandler),this.after("heightChange",this._sizeChangeHandler),this.after("stylesChange",this._updateStyles),this.after("groupMarkersChange",this._drawSeries)},syncUI:function(){var t,n,r,i=this.get("seriesCollection"),s,o=0,u=i?i.length:0,a=this.get("horizontalGridlines"),f=this.get("verticalGridlines");this.get("showBackground")&&(t=this.get("background"),n=this.get("contentBox"),r=this.get("styles").background,r.stroke=r.border,r.stroke.opacity=r.stroke.alpha,r.fill.opacity=r.fill.alpha,r.width=this.get("width"),r.height=this.get("height"),r.type=r.shape,t.set(r));for(;o<u;++o)s=i[o],s instanceof e.CartesianSeries&&s.render();a&&a instanceof e.Gridlines&&a.draw(),f&&f instanceof e.Gridlines&&f.draw()},seriesTypes:null,getSeriesByIndex:function(e){var t=this.get("seriesCollection"),n;return t&&t.length>e&&(n=t[e]),n},getSeriesByKey:function(e){var t=this._seriesDictionary,n;return t&&t.hasOwnProperty(e)&&(n=t[e]),n},addDispatcher:function(e){this._dispatchers||(this._dispatchers=[]),this._dispatchers.push(e)},_seriesCollection:null,_seriesDictionary:null,_parseSeriesCollection:function(t){if(!t)return;var n=t.length,r=0,i,s;this._seriesCollection=[],this._seriesDictionary={},this.seriesTypes=[];for(;r<n;++r){i=t[r];if(!(i instanceof e.CartesianSeries||i instanceof e.PieSeries)){this._createSeries(i);continue}this._addSeries(i)}n=this._seriesCollection.length;for(r=0;r<n;++r)i=this.get("seriesCollection")[r],s=i.get("direction")=="horizontal"?"yKey":"xKey",this._seriesDictionary[i.get(s)]=i},_addSeries:function(t){var n=t.get("type"),r=this.get("seriesCollection"),i=r.length,s=this.seriesTypes,o;t.get("graph")||t.set("graph",this),r.push(t),s.hasOwnProperty(n)||(this.seriesTypes[n]=[]),o=this.seriesTypes[n],t.set("graphOrder",i),t.set("order",o.length),o.push(t),this.addDispatcher(t),t.after("drawingComplete",e.bind(this._drawingCompleteHandler,this)),this.fire("seriesAdded",t)},_createSeries:function(t){var n=t.type,r=this.get("seriesCollection"),i=this.seriesTypes,s,o,u;t.graph=this,i.hasOwnProperty(n)||(i[n]=[]),s=i[n],t.graph=this,t.order=s.length,t.graphOrder=r.length,o=this._getSeries(t.type),u=new o(t),this.addDispatcher(u),u.after("drawingComplete",e.bind(this._drawingCompleteHandler,this)),s.push(u),r.push(u),this.get("rendered")&&u.render()},_seriesMap:{line:e.LineSeries,column:e.ColumnSeries,bar:e.BarSeries,area:e.AreaSeries,candlestick:e.CandlestickSeries,ohlc:e.OHLCSeries,stackedarea:e.StackedAreaSeries,stackedline:e.StackedLineSeries,stackedcolumn:e.StackedColumnSeries,stackedbar:e.StackedBarSeries,markerseries:e.MarkerSeries,spline:e.SplineSeries,areaspline:e.AreaSplineSeries,stackedspline:e.StackedSplineSeries,stackedareaspline:e.StackedAreaSplineSeries,stackedmarkerseries:e.StackedMarkerSeries,pie:e.PieSeries,combo:e.ComboSeries,stackedcombo:e.StackedComboSeries,combospline:e.ComboSplineSeries,stackedcombospline:e.StackedComboSplineSeries},_getSeries:function(e){var t;return s.isString(e)?t=this._seriesMap[e]:t=e,t},_markerEventHandler:function(e){var t=e.type,n=e.currentTarget,r=n.getAttribute("id").split("_"),i=this.getSeriesByIndex(r[1]),s=r[2];i.updateMarkerState(t,s)},_dispatchers:null,_updateStyles:function(){var e=this.get("styles").background,t=e.border;t.opacity=t.alpha,e.stroke=t,e.fill.opacity=e.fill.alpha,this.get("background").set(e),this._sizeChangeHandler()},_sizeChangeHandler:function(t){var n=this.get("horizontalGridlines"),r=this.get("verticalGridlines"),i=this.get("width"),s=this.get("height"),o=this.get("styles").background,u,a;o&&o.border&&(u=o.border.weight||0),this.get("showBackground")&&(a=this.get("background"),i&&s&&(a.set("width",i),a.set("height",s))),this._gridlines&&this._gridlines.clear(),n&&n instanceof e.Gridlines&&n.draw(),r&&r instanceof e.Gridlines&&r.draw(),this._drawSeries()},_drawSeries:function(){if(this._drawing){this._callLater=!0;return}var t,n,r,i=this.get("graphic");i.set("autoDraw",!1),this._callLater=!1,this._drawing=!0,t=this.get("seriesCollection"),n=0,r=t?t.length:0;for(;n<r;++n){t[n].draw();if((!t[n].get("xcoords")||!t[n].get("ycoords"))&&!t[n]instanceof e.PieSeries){this._callLater=!0;break}}this._drawing=!1,this._callLater&&this._drawSeries()},_drawingCompleteHandler:function(t){var n=t.currentTarget,r,i=e.Array.indexOf(this._dispatchers,n);i>-1&&this._dispatchers.splice(i,1),this._dispatchers.length<1&&(r=this.get("graphic"),r.get("autoDraw")||r._redraw(),this.fire("chartRendered"))},_getDefaultStyles:function(){var e={background:{shape:"rect",fill:{color:"#faf9f2"},border:{color:"#dad8c9",weight:1}}};return e},destructor:function(){this._graphic&&(this._graphic.destroy(),this._graphic=null),this._background&&(this._background.get("graphic").destroy(),this._background=null),this._gridlines&&(this._gridlines.get("graphic").destroy(),this._gridlines=null)}},{ATTRS:{x:{setter:function(e){return this.get("boundingBox").setStyle("left",e+"px"),e}},y:{setter:function(e){return this.get("boundingBox").setStyle("top",e+"px"),e}},chart:{},seriesCollection:{getter:function(){return this._seriesCollection},setter:function(e){return this._parseSeriesCollection(e),this._seriesCollection}},showBackground:{value:!0},seriesDictionary:{readOnly:!0,getter:function(){return this._seriesDictionary}},horizontalGridlines:{value:null,setter:function(t){var n=this.get("horizontalGridlines");n&&n instanceof e.Gridlines&&n.remove();if(t instanceof e.Gridlines)return n=t,t.set("graph",this),t;if(t&&t.axis)return n=new e.Gridlines({direction:"horizontal",axis:t.axis,graph:this,styles:t.styles}),n}},verticalGridlines:{value:null,setter:function(t){var n=this.get("verticalGridlines");n&&n instanceof e.Gridlines&&n.remove();if(t instanceof e.Gridlines)return n=t,t.set("graph",this),t;if(t&&t.axis)return n=new e.Gridlines({direction:"vertical",axis:t.axis,graph:this,styles:t.styles}),n}},background:{getter:function(){return this._background||(this._backgroundGraphic=new e.Graphic({render:this.get("contentBox")}),this._backgroundGraphic.get("node").style.zIndex=0,this._background=this._backgroundGraphic.addShape({type:"rect"})),this._background}},gridlines:{readOnly:!0,getter:function(){return this._gridlines||(this._gridlinesGraphic=new e.Graphic({render:this.get("contentBox")}),this._gridlinesGraphic.get("node").style.zIndex=1,this._gridlines=this._gridlinesGraphic.addShape({type:"path"})),this._gridlines}},graphic:{readOnly:!0,getter:function(){return this._graphic||(this._graphic=new e.Graphic({render:this.get("contentBox")}),this._graphic.get("node").style.zIndex=2,this._graphic.set("autoDraw",!1)),this._graphic}},groupMarkers:{value:!1}}}),O.ATTRS={dataProvider:{lazyAdd:!1,valueFn:function(){var e=[];return this._seriesKeysExplicitlySet||(this._seriesKeys=this._buildSeriesKeys(e)),e},setter:function(e){var t=this._setDataValues(e);return this._seriesKeysExplicitlySet||(this._seriesKeys=this._buildSeriesKeys(t)),t}},seriesKeys:{getter:function(){return this._seriesKeys},setter:function(e){return this._seriesKeysExplicitlySet=!0,this._seriesKeys=e,e}},ariaLabel:{value:"Chart Application",setter:function(e){var t=this.get("contentBox");return t&&t.setAttribute("aria-label",e),e}},ariaDescription:{value:"Use the up and down keys to navigate between series. Use the left and right keys to navigate through items in a series.",setter:function(e){return this._description&&(this._description.setContent(""),this._description.appendChild(i.createTextNode(e))),e}},tooltip:{valueFn:"_getTooltip",setter:function(e){return this._updateTooltip(e)}},categoryKey:{value:"category"},categoryType:{value:"category"},interactionType:{value:"marker"},axesCollection:{},graph:{valueFn:"_getGraph"},groupMarkers:{value:!1}},O.prototype={_groupMarkersChangeHandler:function(e){var t=this.get("graph"),n=e.newVal;t&&t.set("groupMarkers",n)},_itemRendered:function(t){this._itemRenderQueue=this._itemRenderQueue.splice(1+e.Array.indexOf(this._itemRenderQueue,t.currentTarget),1),this._itemRenderQueue.length<1&&this._redraw()},_getGraph:function(){var t=new e.Graph({chart:this,groupMarkers:this.get("groupMarkers")});return t.after("chartRendered",e.bind(function(e){this.fire("chartRendered")},this)),t},getSeries:function(e){var t=null,n=this.get("graph");return n&&(s.isNumber(e)?t=n.getSeriesByIndex(e):t=n.getSeriesByKey(e)),t},getAxisByKey:function(e){var t,n=this.get("axes");return n&&n.hasOwnProperty(e)&&(t=n[e]),t},getCategoryAxis:function(){var e,t=this.get("categoryKey"),n=this.get("axes");return n.hasOwnProperty(t)&&(e=n[t]),e},_direction:"horizontal",_dataProvider:null,_setDataValues:function(e){if(s.isArray(e[0])){var t,n=[],r=e[0],i=0,o=r.length,u,a=e.length;for(;i<o;++i){t={category:r[i]};for(u=1;u<a;++u)t["series"+u]=e[u][i];n[i]=t}return n}return e},_seriesCollection:null,_setSeriesCollection:function(e){this._seriesCollection=e},_getAxisClass:function(e){return this._axisClass[e]},_axisClass:{stacked:e.StackedAxis,numeric:e.NumericAxis,category:e.CategoryAxis,time:e.TimeAxis},_axes:null,initializer:function(){this._itemRenderQueue=[],this._seriesIndex=-1,this._itemIndex=-1,this.after("dataProviderChange",this._dataProviderChangeHandler)},renderUI:function(){var e=this.get("tooltip"),t=this.get("boundingBox"),n=this.get("contentBox");t.setStyle("position","absolute"),n.setStyle("position","absolute"),this._addAxes(),this._addSeries(),e&&e.show&&this._addTooltip(),this._setAriaElements(t,n)},_setAriaElements:function(e,t){var n=this._getAriaOffscreenNode(),r=this.get("id")+"_description",s=this._getAriaOffscreenNode();t.set("tabIndex",0),t.set("role","img"),t.setAttribute("aria-label",this.get("ariaLabel")),t.setAttribute("aria-describedby",r),n.set("id",r),n.set("tabIndex",-1),n.appendChild(i.createTextNode(this.get("ariaDescription"))),s.set("id","live-region"),s.set("aria-live","polite"),s.set("aria-atomic","true"),s.set("role","status"),e.setAttribute("role","application"),e.appendChild(n),e.appendChild(s),this._description=n,this._liveRegion=s},_getAriaOffscreenNode:function(){var t=e.Node.create("<div></div>"),n=e.UA.ie,r=n&&n<8?"rect(1px 1px 1px 1px)":"rect(1px, 1px, 1px, 1px)";return t.setStyle("position","absolute"),t.setStyle("height","1px"),t.setStyle("width","1px"),t.setStyle("overflow","hidden"),t.setStyle("clip",r),t},syncUI:function(){this._redraw()},bindUI:function(){this.after("tooltipChange",e.bind(this._tooltipChangeHandler,this)),this.after("widthChange",this._sizeChanged),this.after("heightChange",this._sizeChanged),this.after("groupMarkersChange",this._groupMarkersChangeHandler);var t=this.get("tooltip"),n="mouseout",o="mouseover",u=this.get("contentBox"),a=this.get("interactionType"),f=0,l,c="."+p,h=r&&"ontouchstart"in r&&!(e.UA.chrome&&e.UA.chrome<6);e.on("keydown",e.bind(function(e){var t=e.keyCode,n=parseFloat(t),r;n>36&&n<41&&(e.halt(),r=this._getAriaMessage(n),this._liveRegion.setContent(""),this._liveRegion.appendChild(i.createTextNode(r)))},this),this.get("contentBox")),a=="marker"?(n=t.hideEvent,o=t.showEvent,h?(e.delegate("touchend",e.bind(this._markerEventDispatcher,this),u,c),e.on("touchend",e.bind(function(e){e.halt(!0),this._activeMarker&&(this._activeMarker=null,this.hideTooltip(e))},this))):(e.delegate("mouseenter",e.bind(this._markerEventDispatcher,this),u,c),e.delegate("mousedown",e.bind(this._markerEventDispatcher,this),u,c),e.delegate("mouseup",e.bind(this._markerEventDispatcher,this),u,c),e.delegate("mouseleave",e.bind(this._markerEventDispatcher,this),u,c),e.delegate("click",e.bind(this._markerEventDispatcher,this),u,c),e.delegate("mousemove",e.bind(this._positionTooltip,this),u,c))):a=="planar"&&(h?this._overlay.on("touchend",e.bind(this._planarEventDispatcher,this)):(this._overlay.on("mousemove",e.bind(this._planarEventDispatcher,this)),this.on("mouseout",this.hideTooltip)));if(t){this.on("markerEvent:touchend",e.bind(function(e){var n=e.series.get("markers")[e.index];this._activeMarker&&n===this._activeMarker?(this._activeMarker=null,this.hideTooltip(e)):(this._activeMarker=n,t.markerEventHandler.apply(this,[e]))},this));if(n&&o&&n==o)this.on(a+"Event:"+n,this.toggleTooltip);else{o&&this.on(a+"Event:"+o,t[a+"EventHandler"]);if(n){if(s.isArray(n)){l=n.length;for(;f<l;++f)this.on(a+"Event:"+n[f],this.hideTooltip)}this.on(a+"Event:"+n,this.hideTooltip)}}}},_markerEventDispatcher:function(e){var t=e.type,n=this.get("contentBox"),r=e.currentTarget,i=r.getAttribute("id").split("_"),s=i.pop(),o=i.pop(),u=this.getSeries(parseInt(o,10)),a=this.getSeriesItems(u,s),f=e&&e.hasOwnProperty("changedTouches"),l=f?e.changedTouches[0].pageX:e.pageX,c=f?e.changedTouches[0].pageY:e.pageY,h=l-n.getX(),p=c-n.getY();t=="mouseenter"?t="mouseover":t=="mouseleave"&&(t="mouseout"),u.updateMarkerState(t,s),e.halt(),this.fire("markerEvent:"+t,{originEvent:e,pageX:l,pageY:c,categoryItem:a.category,valueItem:a.value,node:r,x:h,y:p,series:u,index:s,seriesIndex:o})},_dataProviderChangeHandler:function(t){var n=t.newVal,r,i,s;this._seriesIndex=-1,this._itemIndex=-1,this instanceof e.CartesianChart&&(this.set("axes",this.get("axes")),this.set("seriesCollection",this.get("seriesCollection"))),r=this.get("axes");if(r)for(i in r)r.hasOwnProperty(i)&&(s=r[i],s instanceof e.Axis&&(s.get("position")!="none"&&this._addToAxesRenderQueue(s),s.set("dataProvider",n)))},toggleTooltip:function(e){var t=this.get("tooltip");t.visible?this.hideTooltip():t.markerEventHandler.apply(this,[e])},_showTooltip:function(e,t,n){var r=this.get("tooltip"),i=r.node;e&&(r.visible=!0,r.setTextFunction(i,e),i.setStyle("top",n+"px"),i.setStyle("left",t+"px"),i.setStyle("visibility","visible"))},_positionTooltip:function(e){var t=this.get("tooltip"),n=t.node,r=this.get("contentBox"),i=e.pageX+10-r.getX(),s=e.pageY+10-r.getY();n&&(n.setStyle("left",i+"px"),n.setStyle("top",s+"px"))},hideTooltip:function(){var e=this.get("tooltip"),t=e.node;e.visible=!1,t.set("innerHTML",""),t.setStyle("left",-1e4),t.setStyle("top",-1e4),t.setStyle("visibility","hidden")},_addTooltip:function(){var e=this.get("tooltip"),t=this.get("id")+"_tooltip",n=this.get("contentBox"),r=i.getElementById(t);r&&n.removeChild(r),e.node.set("id",t),e.node.setStyle("visibility","hidden"),n.appendChild(e.node)},_updateTooltip:function(t){var n=this.get("tooltip")||this._getTooltip(),r,i,o,u={markerLabelFunction:"markerLabelFunction",planarLabelFunction:"planarLabelFunction",setTextFunction:"setTextFunction",showEvent:"showEvent",hideEvent:"hideEvent",markerEventHandler:"markerEventHandler",planarEventHandler:"planarEventHandler",show:"show"};if(s.isObject(t)){i=t.styles,o=e.one(t.node)||n.node;if(i)for(r in i)i.hasOwnProperty(r)&&o.setStyle(r,i[r]);for(r in u)t.hasOwnProperty(r)&&(n[r]=t[r]);n.node=o}return n},_getTooltip:function(){var t=i.createElement("div"),n=h("chart-tooltip"),r={setTextFunction:this._setText,markerLabelFunction:this._tooltipLabelFunction,planarLabelFunction:this._planarLabelFunction,show:!0,hideEvent:"mouseout",showEvent:"mouseover",markerEventHandler:function(e){var t=this.get("tooltip"),n=t.markerLabelFunction.apply(this,[e.categoryItem,e.valueItem,e.index,e.series,e.seriesIndex]);this._showTooltip(n,e.x+10,e.y+10)},planarEventHandler:function(e){var t=this.get("tooltip"),n,r=this.get("categoryAxis");n=t.planarLabelFunction.apply(this,[r,e.valueItem,e.index,e.items,e.seriesIndex]),this._showTooltip(n,e.x+10,e.y+10)}};return t=e.one(t),t.set("id",this.get("id")+"_tooltip"),t.setStyle("fontSize","85%"),t.setStyle("opacity","0.83"),t.setStyle("position","absolute"),t.setStyle("paddingTop","2px"),t.setStyle("paddingRight","5px"),t.setStyle("paddingBottom","4px"),t.setStyle("paddingLeft","2px"),t.setStyle("backgroundColor","#fff"),t.setStyle("border","1px solid #dbdccc"),t.setStyle("pointerEvents","none"),t.setStyle("zIndex",3),t.setStyle("whiteSpace","noWrap"),t.setStyle("visibility","hidden"),t.addClass(n),r.node=e.one(t),r},_planarLabelFunction:function(e,t,n,r,o){var u=i.createElement("div"),a,f=0,l=r.length,c,h,p,d;e&&(h=e.get("labelFunction").apply(this,[e.getKeyValueAt(this.get("categoryKey"),n),e.get("labelFormat")]),s.isObject(h)||(h=i.createTextNode(h)),u.appendChild(h));for(;f<l;++f)d=r[f],d.get("visible")&&(a=t[f],c=a.axis,p=c.get("labelFunction").apply(this,[c.getKeyValueAt(a.key,n),c.get("labelFormat")]),u.appendChild(i.createElement("br")),u.appendChild(i.createTextNode(a.displayName)),u.appendChild(i.createTextNode(": ")),s.isObject(p)||(p=i.createTextNode(p)),u.appendChild(p));return u},_tooltipLabelFunction:function(e,t,n,r,o){var u=i.createElement("div"),a=e.axis.get("labelFunction").apply(this,[e.value,e.axis.get("labelFormat")]),f=t.axis.get("labelFunction").apply(this,[t.value,t.axis.get("labelFormat")]);return u.appendChild(i.createTextNode(e.displayName)),u.appendChild(i.createTextNode(": ")),s.isObject(a)||(a=i.createTextNode(a)),u.appendChild(a),u.appendChild(i.createElement("br")),u.appendChild(i.createTextNode(t.displayName)),u.appendChild(i.createTextNode(": ")),s.isObject(f)||(f=i.createTextNode(f)),u.appendChild(f),u},_tooltipChangeHandler:function(e){if(this.get("tooltip")){var t=this.get("tooltip"),n=t.node,r=t.show,i=this.get("contentBox");n&&r&&(i.contains(n)||this._addTooltip())}},_setText:function(e,t){e.setContent(""),s.isNumber(t)?t+="":t||(t=""),o(t)&&(t=i.createTextNode(t)),e.appendChild(t)},_getAllKeys:function(e){var t=0,n=e.length,r,i,s={};for(;t<n;++t){r=e[t];for(i in r)r.hasOwnProperty(i)&&(s[i]=!0)}return s},_buildSeriesKeys:function(e){var t,n=this.get("categoryKey"),r=[],i;if(this._seriesKeysExplicitlySet)return this._seriesKeys;t=this._getAllKeys(e);for(i in t)t.hasOwnProperty(i)&&i!=n&&r.push(i);return r}},e.ChartBase=O,e.CartesianChart=e.Base.create("cartesianChart",e.Widget,[e.ChartBase],{renderUI:function(){var t=this.get("boundingBox"),n=this.get("contentBox"),r=this.get("tooltip"),s,o=h("overlay");t.setStyle("position","absolute"),n.setStyle("position","absolute"),this._addAxes(),this._addGridlines(),this._addSeries(),r&&r.show&&this._addTooltip(),this.get("styles"),this.get("interactionType")=="planar"&&(s=i.createElement("div"),this.get("contentBox").appendChild(s),this._overlay=e.one(s),this._overlay.set("id",this.get("id")+"_overlay"),this._overlay.setStyle("position","absolute"),this._overlay.setStyle("background","#fff"),this._overlay.setStyle("opacity",0),this._overlay.addClass(o),this._overlay.setStyle("zIndex",4)),this._setAriaElements(t,n),this._redraw()},_planarEventDispatcher:function(e){var t=this.get("graph"),n=this.get("boundingBox"),r=t.get("contentBox"),i=e&&e.hasOwnProperty("changedTouches"),s=i?e.changedTouches[0].pageX:e.pageX,o=i?e.changedTouches[0].pageY:e.pageY,u=s-n.getX(),a=o-n.getY(),f={x:s-r.getX(),y:o-r.getY()},l=t.get("seriesCollection"),c,h=0,p,d=this._selectedIndex,v,m=[],g=[],y=[],b=this.get("direction"),w,E,S,x,T,N,C;e.halt(!0),b=="horizontal"?(E="x",S="y"):(S="x",E="y"),x=f[E];if(l){N=l.length;while(h<N&&!T)l[h]&&(T=l[h].get(E+"MarkerPlane")),h++}if(T){N=T.length;for(h=0;h<N;++h)if(x<=T[h].end&&x>=T[h].start){p=h;break}N=l.length;for(h=0;h<N;++h)c=l[h],C=c.get(S+"coords"),w=c.get("markers"),w&&!isNaN(d)&&d>-1&&c.updateMarkerState("mouseout",d),C&&C[p]>-1&&(w&&!isNaN(p)&&p>-1&&c.updateMarkerState("mouseover",p),v=this.getSeriesItems(c,p),g.push(v.category),y.push(v.value),m.push(c));this._selectedIndex=p,p>-1?this.fire("planarEvent:mouseover",{categoryItem:g,valueItem:y,x:u,y:a,pageX:s,pageY:o,items:m,index:p,originEvent:e}):this.fire("planarEvent:mouseout")}},_type:"combo",_itemRenderQueue:null,_addToAxesRenderQueue:function(t){this._itemRenderQueue||(this._itemRenderQueue=[]),e.Array.indexOf(this._itemRenderQueue,t)<0&&this._itemRenderQueue.push(t)},_addToAxesCollection:function(e,t){var n=this.get(e+"AxesCollection");n||(n=[],this.set(e+"AxesCollection",n)),n.push(t)},_getDefaultSeriesCollection:function(){var e,t=this.get("dataProvider");return t&&(e=this._parseSeriesCollection()),e},_parseSeriesCollection:function(t){var n=this.get("direction"),r=[],i,s,o=[],u,a=this.get("seriesKeys").concat(),f,l,c,h=this.get("type"),p,d,v,m,g=[],y=this.get("categoryKey"),b=this.get("showMarkers"),w=this.get("showAreaFill"),E=this.get("showLines");t=t||[],n=="vertical"?(i="yAxis",d="yKey",s="xAxis",v="xKey"):(i="xAxis",d="xKey",s="yAxis",v="yKey"),c=t.length;while(t&&t.length>0)u=t.shift(),p=this._getBaseAttribute(u,v),p?(l=e.Array.indexOf(a,p),l>-1?(a.splice(l,1),o.push(p),r.push(u)):g.push(u)):g.push(u);while(g.length>0)u=g.shift(),a.length>0?(p=a.shift(),this._setBaseAttribute(u,v,p),o.push(p),r.push(u)):u instanceof e.CartesianSeries&&u.destroy(!0);a.length>0&&(o=o.concat(a)),c=o.length;for(f=0;f<c;++f){u=r[f]||{type:h};if(u instanceof e.CartesianSeries){this._parseSeriesAxes(u);continue}u[d]=u[d]||y,u[v]=u[v]||a.shift(),u[i]=this._getCategoryAxis(),u[s]=this._getSeriesAxis(u[v]),u.type=u.type||h,u.direction=u.direction||n;if(u.type=="combo"||u.type=="stackedcombo"||u.type=="combospline"||u.type=="stackedcombospline")w!==null&&(u.showAreaFill=u.showAreaFill!==null&&u.showAreaFill!==undefined?u.showAreaFill:w),b!==null&&(u.showMarkers=u.showMarkers!==null&&u.showMarkers!==undefined?u.showMarkers:b),E!==null&&(u.showLines=u.showLines!==null&&u.showLines!==undefined?u.showLines:E);r[f]=u}return r&&(m=this.get("graph"),m.set("seriesCollection",r),r=m.get("seriesCollection")),r},_parseSeriesAxes:function(t){var n=this.get("axes"),r=t.get("xAxis"),i=t.get("yAxis"),o=e.Axis,u;r&&!(r instanceof o)&&s.isString(r)&&n.hasOwnProperty(r)&&(u=n[r],u instanceof o&&t.set("xAxis",u)),i&&!(i instanceof o)&&s.isString(i)&&n.hasOwnProperty(i)&&(u=n[i],u instanceof o&&t.set("yAxis",u))},_getCategoryAxis:function(){var e,t=this.get("axes"),n=this.get("categoryAxisName")||this.get("categoryKey");return e=t[n],e},_getSeriesAxis:function(e,t){var n=this.get("axes"),r,i,s;if(n)if(t&&n.hasOwnProperty(t))s=n[t];else for(r in n)if(n.hasOwnProperty(r)){i=n[r].get("keys");if(i&&i.hasOwnProperty(e)){s=n[r];break}}return s},_getBaseAttribute:function(t,n){return t instanceof e.Base?t.get(n):t.hasOwnProperty(n)?t[n]:null},_setBaseAttribute:function(t,n,r){t instanceof e.Base?t.set(n,r):t[n]=r},_setAxes:function(t){var n=this._parseAxes(t),r={},i={edgeOffset:"edgeOffset",position:"position",overlapGraph:"overlapGraph",labelFunction:"labelFunction",labelFunctionScope:"labelFunctionScope",labelFormat:"labelFormat",appendLabelFunction:"appendLabelFunction",appendTitleFunction:"appendTitleFunction",maximum:"maximum",minimum:"minimum",roundingMethod:"roundingMethod",alwaysShowZero:"alwaysShowZero",title:"title",width:"width",height:"height"},s=this.get("dataProvider"),o,u,a,f,l,c,h,p,d;for(u in n)if(n.hasOwnProperty(u)){c=n[u];if(c instanceof e.Axis)f=c;else{f=null,p={},p.dataProvider=c.dataProvider||s,p.keys=c.keys,c.hasOwnProperty("roundingUnit")&&(p.roundingUnit=c.roundingUnit),a=c.position,c.styles&&(p.styles=c.styles),p.position=c.position;for(o in i)i.hasOwnProperty(o)&&c.hasOwnProperty(o)&&(p[o]=c[o]);t&&(f=this.getAxisByKey(u)),f&&f instanceof e.Axis?(l=f.get("position"),a!=l&&(l!="none"&&(d=this.get(l+"AxesCollection"),d.splice(e.Array.indexOf(d,f),1)),a!="none"&&this._addToAxesCollection(a,f)),f.setAttrs(p)):(h=this._getAxisClass(c.type),f=new h(p),f.after("axisRendered",e.bind(this._itemRendered,this)))}f&&(d=this.get(a+"AxesCollection"),d&&e.Array.indexOf(d,f)>0&&f.set("overlapGraph",!1),r[u]=f)}return r},_addAxes:function(){var t=this.get("axes"),n,r,i,s=this.get("width"),o=this.get("height"),u=e.Node.one(this._parentNode);this._axesCollection||(this._axesCollection=[]);for(n in t)t.hasOwnProperty(n)&&(r=t[n],r instanceof e.Axis&&(s||(this.set("width",u.get("offsetWidth")),s=this.get("width")),o||(this.set("height",u.get("offsetHeight")),o=this.get("height")),this._addToAxesRenderQueue(r),i=r.get("position"),this.get(i+"AxesCollection")?this.get(i+"AxesCollection").push(r):this.set(i+"AxesCollection",[r]),this._axesCollection.push(r),r.get("keys").hasOwnProperty(this.get("categoryKey"))&&this.set("categoryAxis",r),r.render(this.get("contentBox"))))},_addSeries:function(){var e=this.get("graph"),t=this.get("seriesCollection");e.render(this.get("contentBox"))},_addGridlines:function(){var t=this.get("graph"),n=this.get("horizontalGridlines"),r=this.get("verticalGridlines"),i=this.get("direction"),s=this.get("leftAxesCollection"),o=this.get("rightAxesCollection"),u=this.get("bottomAxesCollection"),a=this.get("topAxesCollection"),f,l=this.get("categoryAxis"),c,h;this._axesCollection&&(f=this._axesCollection.concat(),f.splice(e.Array.indexOf(f,l),1)),n&&(s&&s[0]?c=s[0]:o&&o[0]?c=o[0]:c=i=="horizontal"?l:f[0],!this._getBaseAttribute(n,"axis")&&c&&this._setBaseAttribute(n,"axis",c),this._getBaseAttribute(n,"axis")&&t.set("horizontalGridlines",n)),r&&(u&&u[0]?h=u[0]:a&&a[0]?h=a[0]:h=i=="vertical"?l:f[0],!this._getBaseAttribute(r,"axis")&&h&&this._setBaseAttribute(r,"axis",h),this._getBaseAttribute(r,"axis")&&t.set("verticalGridlines",r))},_getDefaultAxes:function(){var e;return this.get("dataProvider")&&(e=this._parseAxes()),e},_parseAxes:function(t){var n=this.get("categoryKey"),r,i,o,u={},a=[],f=this.get("categoryAxisName")||this.get("categoryKey"),l=this.get("valueAxisName"),c=this.get("seriesKeys").concat(),h,p,d,v,m,g=this.get("direction"),y,b,w=[],E=this.get("stacked")?"stacked":"numeric";g=="vertical"?(y="bottom",b="left"):(y="left",b="bottom");if(t)for(h in t)if(t.hasOwnProperty(h)){r=t[h],o=this._getBaseAttribute(r,"keys"),i=this._getBaseAttribute(r,"type");if(i=="time"||i=="category")f=h,this.set("categoryAxisName",h),s.isArray(o)&&o.length>0&&(n=o[0],this.set("categoryKey",n)),u[h]=r;else if(h==f)u[h]=r;else{u[h]=r;if(h!=l&&o&&s.isArray(o)){v=o.length;for(d=0;d<v;++d)a.push(o[d]);w.push(u[h])}this._getBaseAttribute(u[h],"type")||this._setBaseAttribute(u[h],"type",E),this._getBaseAttribute(u[h],"position")||this._setBaseAttribute(u[h],"position",this._getDefaultAxisPosition(u[h],w,y))}}m=e.Array.indexOf(c,n),m>-1&&c.splice(m,1),p=a.length;for(h=0;h<p;++h)m=e.Array.indexOf(c,a[h]),m>-1&&c.splice(m,1);return u.hasOwnProperty(f)||(u[f]={}),this._getBaseAttribute(u[f],"keys")||this._setBaseAttribute(u[f],"keys",[n]),this._getBaseAttribute(u[f],"position")||this._setBaseAttribute(u[f],"position",b),this._getBaseAttribute(u[f],"type")||this._setBaseAttribute(u[f],"type",this.get("categoryType")),!u.hasOwnProperty(l)&&c&&c.length>0&&(u[l]={keys:c},w.push(u[l])),a.length>0&&(c.length>0?c=a.concat(c):c=a),u.hasOwnProperty(l)&&(this._getBaseAttribute(u[l],"position")||this._setBaseAttribute(u[l],"position",this._getDefaultAxisPosition(u[l],w,y)),this._setBaseAttribute(u[l],"type",E),this._setBaseAttribute(u[l],"keys",c)),this._seriesKeysExplicitlySet||(this._seriesKeys=c),u},_getDefaultAxisPosition:function(t,n,r){var i=this.get("direction"),s=e.Array.indexOf(n,t);return n[s-1]&&n[s-1].position&&(i=="horizontal"?n[s-1].position=="left"?r="right":n[s-1].position=="right"&&(r="left"):n[s-1].position=="bottom"?r="top":r="bottom"),r},getSeriesItems:function(e,t){var n=e.get("xAxis"),r=e.get("yAxis"),i=e.get("xKey"),s=e.get("yKey"),o,u;return this.get("direction")=="vertical"?(o={axis:r,key:s,value:r.getKeyValueAt(s,t)},u={axis:n,key:i,value:n.getKeyValueAt(i,t)}):(u={axis:r,key:s,value:r.getKeyValueAt(s,t)},o={axis:n,key:i,value:n.getKeyValueAt(i,t)}),o.displayName=e.get("categoryDisplayName"),u.displayName=e.get("valueDisplayName"),o.value=o.axis.getKeyValueAt(o.key,t),u.value=u.axis.getKeyValueAt(u.key,t),{category:o,value:u}},_sizeChanged:function(e){if(this._axesCollection){var t=this._axesCollection,n=0,r=t.length;for(;n<r;++n)this._addToAxesRenderQueue(t[n]);this._redraw()}},_getTopOverflow:function(e,t,n){var r=0,i,s=0,o;if(e){i=e.length;for(;r<i;++r)o=e[r],s=Math.max(s,Math.abs(o.getMaxLabelBounds().top)-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}if(t){r=0,i=t.length;for(;r<i;++r)o=t[r],s=Math.max(s,Math.abs(o.getMaxLabelBounds().top)-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}return s},_getRightOverflow:function(e,t,n){var r=0,i,s=0,o;if(e){i=e.length;for(;r<i;++r)o=e[r],s=Math.max(s,o.getMaxLabelBounds().right-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}if(t){r=0,i=t.length;for(;r<i;++r)o=t[r],s=Math.max(s,o.getMaxLabelBounds().right-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}return s},_getLeftOverflow:function(e,t,n){var r=0,i,s=0,o;if(e){i=e.length;for(;r<i;++r)o=e[r],s=Math.max(s,Math.abs(o.getMinLabelBounds().left)-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}if(t){r=0,i=t.length;for(;r<i;++r)o=t[r],s=Math.max(s,Math.abs(o.getMinLabelBounds().left)-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}return s},_getBottomOverflow:function(e,t,n){var r=0,i,s=0,o;if(e){i=e.length;for(;r<i;++r)o=e[r],s=Math.max(s,o.getMinLabelBounds().bottom-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}if(t){r=0,i=t.length;for(;r<i;++r)o=t[r],s=Math.max(s,o.getMinLabelBounds().bottom-o.getEdgeOffset(o.get("styles").majorTicks.count,n)*.5)}return s},_redraw:function(){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1;var e=this.get("width"),t=this.get("height"),n=0,r=0,i=0,s=0,o=this.get("leftAxesCollection"),u=this.get("rightAxesCollection"),a=this.get("topAxesCollection"),f=this.get("bottomAxesCollection"),l=0,c,h,p="visible",d=this.get("graph"),v,m,g,y,b,w,E,S,x=this.get("allowContentOverflow"),T,N,C,k,L,A={};if(o){C=[],c=o.length;for(l=c-1;l>-1;--l)C.unshift(n),n+=o[l].get("width")}if(u){N=[],c=u.length,l=0;for(l=c-1;l>-1;--l)r+=u[l].get("width"),N.unshift(e-r)}if(a){k=[],c=a.length;for(l=c-1;l>-1;--l)k.unshift(i),i+=a[l].get("height")}if(f){L=[],c=f.length;for(l=c-1;l>-1;--l)s+=f[l].get("height"),L.unshift(t-s)}b=e-(n+r),w=t-(s+i),A.left=n,A.top=i,A.bottom=t-s,A.right=e-r;if(!x){v=this._getTopOverflow(o,u),m=this._getBottomOverflow(o,u),g=this._getLeftOverflow(f,a),y=this._getRightOverflow(f,a),T=v-i;if(T>0){A.top=v;if(k){l=0,c=k.length;for(;l<c;++l)k[l]+=T}}T=m-s;if(T>0){A.bottom=t-m;if(L){l=0,c=L.length;for(;l<c;++l)L[l]-=T}}T=g-n;if(T>0){A.left=g;if(C){l=0,c=C.length;for(;l<c;++l)C[l]+=T}}T=y-r;if(T>0){A.right=e-y;if(N){l=0,c=N.length;for(;l<c;++l)N[l]-=T}}}b=A.right-A.left,w=A.bottom-A.top,E=A.left,S=A.top;if(a){c=a.length,l=0;for(;l<c;l++)h=a[l],h.get("width")!==b&&h.set("width",b),h.get("boundingBox").setStyle("left",E+"px"),h.get("boundingBox").setStyle("top",k[l]+"px");h._hasDataOverflow()&&(p="hidden")}if(f){c=f.length,l=0;for(;l<c;l++)h=f[l],h.get("width")!==b&&h.set("width",b),h.get("boundingBox").setStyle("left",E+"px"),h.get("boundingBox").setStyle("top",L[l]+"px");h._hasDataOverflow()&&(p="hidden")}if(o){c=o.length,l=0;for(;l<c;++l)h=o[l],h.get("boundingBox").setStyle("top",S+"px"),h.get("boundingBox").setStyle("left",C[l]+"px"),h.get("height")!==w&&h.set("height",w);h._hasDataOverflow()&&(p="hidden")}if(u){c=u.length,l=0;for(;l<c;++l)h=u[l],h.get("boundingBox").setStyle("top",S+"px"),h.get("boundingBox").setStyle("left",N[l]+"px"),h.get("height")!==w&&h.set("height",w);h._hasDataOverflow()&&(p="hidden")}this._drawing=!1;if(this._callLater){this._redraw();return}d&&(d.get("boundingBox").setStyle("left",E+"px"),d.get("boundingBox").setStyle("top",S+"px"),d.set("width",b),d.set("height",w),d.get("boundingBox").setStyle("overflow",p)),this._overlay&&(this._overlay.setStyle("left",E+"px"),this._overlay.setStyle("top",S+"px"),this._overlay.setStyle("width",b+"px"),this._overlay.setStyle("height",w+"px"))},destructor:function(){var t=this.get("graph"),n=0,r,i=this.get("seriesCollection"),s=this._axesCollection,o=this.get("tooltip").node;this._description&&(this._description.empty(),this._description.remove(!0)),this._liveRegion&&(this._liveRegion.empty(),this._liveRegion.remove(!0)),r=i?i.length:0;for(;n<r;++n)i[n]instanceof e.CartesianSeries&&i[n].destroy(!0);r=s?s.length:0;for(n=0;n<r;++n)s[n]instanceof e.Axis&&s[n].destroy(!0);t&&t.destroy(!0),o&&(o.empty(),o.remove(!0)),this._overlay&&(this._overlay.empty(),this._overlay.remove(!0))},_getAriaMessage:function(e){var t="",n,r,i,s,o=this._seriesIndex,u=this._itemIndex,a=this.get("seriesCollection"),f=a.length,l;return e%2===0?(f>1?(e===38?o=o<1?f-1:o-1:e===40&&(o=o>=f-1?0:o+1),this._itemIndex=-1):o=0,this._seriesIndex=o,n=this.getSeries(parseInt(o,10)),t=n.get("valueDisplayName")+" series."):(o>-1?(t="",n=this.getSeries(parseInt(o,10))):(o=0,this._seriesIndex=o,n=this.getSeries(parseInt(o,10)),t=n.get("valueDisplayName")+" series."),l=n._dataLength?n._dataLength:0,e===37?u=u>0?u-1:l-1:e===39&&(u=u>=l-1?0:u+1),this._itemIndex=u,r=this.getSeriesItems(n,u),i=r.category,s=r.value,i&&s&&i.value&&s.value?(t+=i.displayName+": "+i.axis.formatLabel.apply(this,[i.value,i.axis.get("labelFormat")])+", ",t+=s.displayName+": "+s.axis.formatLabel.apply(this,[s.value,s.axis.get("labelFormat")])+", "):t+="No data available.",t+=u+1+" of "+l+". "),t}},{ATTRS:{allowContentOverflow:{value:!1},axesStyles:{getter:function(){var t=this.get("axes"),n,r=this._axesStyles;if(t)for(n in t)t.hasOwnProperty(n)&&t[n]instanceof e.Axis&&(r||(r={}),r[n]=t[n].get("styles"));return r},setter:function(e){var t=this.get("axes"),n;for(n in e)e.hasOwnProperty(n)&&t.hasOwnProperty(n)&&this._setBaseAttribute(t[n],"styles",e[n])}},seriesStyles:{getter:function(){var e=this._seriesStyles,t=this.get("graph"),n,r;if(t){n=t.get("seriesDictionary");if(n){e={};for(r in n)n.hasOwnProperty(r)&&(e[r]=n[r].get("styles"))}}return e},setter:function(e){var t,n,r;if(s.isArray(e)){r=this.get("seriesCollection"),t=0,n=e.length;for(;t<n;++t)this._setBaseAttribute(r[t],"styles",e[t])}else for(t in e)e.hasOwnProperty(t)&&(r=this.getSeries(t),this._setBaseAttribute(r,"styles",e[t]))}},graphStyles:{getter:function(){var e=this.get("graph");return e?e.get("styles"):this._graphStyles},setter:function(e){var t=this.get("graph");this._setBaseAttribute(t,"styles",e)}},styles:{getter:function(){var e={axes:this.get("axesStyles"),series:this.get("seriesStyles"),graph:this.get("graphStyles")};return e},setter:function(e){e.hasOwnProperty("axes")&&(this.get("axesStyles")?this.set("axesStyles",e.axes):this._axesStyles=e.axes),e.hasOwnProperty("series")&&(this.get("seriesStyles")?this.set("seriesStyles",e.series):this._seriesStyles=e.series),e.hasOwnProperty("graph")&&this.set("graphStyles",e.graph)}},axes:{valueFn:"_getDefaultAxes",setter:function(e){return this.get("dataProvider")&&(e=this._setAxes(e)),e}},seriesCollection:{valueFn:"_getDefaultSeriesCollection",setter:function(e){return this.get("dataProvider")&&(e=this._parseSeriesCollection(e)),e}},leftAxesCollection:{},bottomAxesCollection:{},rightAxesCollection:{},topAxesCollection:{},stacked:{value:!1},direction:{getter:function(){var e=this.get("type");return e=="bar"?"vertical":e=="column"?"horizontal":this._direction},setter:function(e){return this._direction=e,this._direction}},showAreaFill:{},showMarkers:{},showLines:{},categoryAxisName:{},valueAxisName:{value:"values"},horizontalGridlines:{getter:function(){var e=this.get("graph");return e?e.get("horizontalGridlines"):this._horizontalGridlines},setter:function(e){var t=this.get("graph");e&&!s.isObject(e)&&(e={}),t?t.set("horizontalGridlines",e):this._horizontalGridlines=e}},verticalGridlines:{getter:function(){var e=this.get("graph");return e?e.get("verticalGridlines"):this._verticalGridlines},setter:function(e){var t=this.get("graph");e&&!s.isObject(e)&&(e={}),t?t.set("verticalGridlines",e):this._verticalGridlines=e}},type:{getter:function(){return this.get("stacked")?"stacked"+this._type:this._type},setter:function(e){return this._type=="bar"?e!="bar"&&this.set("direction","horizontal"):e=="bar"&&this.set("direction","vertical"),this._type=e,this._type}},categoryAxis:{}}}),e.PieChart=e.Base.create("pieChart",e.Widget,[e.ChartBase],{_getSeriesCollection:function(){if(this._seriesCollection)return this._seriesCollection;var e=this.get("axes"),t=[],n,r=0,i,s=this.get("type"),o,u="categoryAxis",a="categoryKey",f="valueAxis",l="valueKey";if(e){n=e.values.get("keyCollection"),o=e.category.get("keyCollection")[0],i=n.length;for(;r<i;++r)t[r]={type:s},t[r][u]="category",t[r][f]="values",t[r][a]=o,t[r][l]=n[r]}return this._seriesCollection=t,t},_parseAxes:function(t){this._axes||(this._axes={});var n,r,i,s,o,u,a=this.get("type"),f=this.get("width"),l=this.get("height"),c=e.Node.one(this._parentNode);f||(this.set("width",c.get("offsetWidth")),f=this.get("width")),l||(this.set("height",c.get("offsetHeight")),l=this.get("height"));for(n in t)t.hasOwnProperty(n)&&(s=t[n],r=a=="pie"?"none":s.position,u=this._getAxisClass(s.type),o={dataProvider:this.get("dataProvider")},s.hasOwnProperty("roundingUnit")&&(o.roundingUnit=s.roundingUnit),o.keys=s.keys,o.width=f,o.height=l,o.position=r,o.styles=s.styles,i=new u(o),i.on("axisRendered",e.bind(this._itemRendered,this)),this._axes[n]=i)},_addAxes:function(){var e=this.get("axes"),t,n,r;e||(this.set("axes",this._getDefaultAxes()),e=this.get("axes")),this._axesCollection||(this._axesCollection=[]);for(t in e)e.hasOwnProperty(t)&&(n=e[t],r=n.get("position"),this.get(r+"AxesCollection")?this.get(r+"AxesCollection").push(n):this.set(r+"AxesCollection",[n]),this._axesCollection.push(n))},_addSeries:function(){var e=this.get("graph"),t=this.get("seriesCollection");this._parseSeriesAxes(t),e.set("showBackground",!1),e.set("width",this.get("width")),e.set("height",this.get("height")),e.set("seriesCollection",t),this._seriesCollection=e.get("seriesCollection"),e.render(this.get("contentBox"))},_parseSeriesAxes:function(t){var n=0,r=t.length,i,s=this.get("axes"),o;for(;n<r;++n){i=t[n];if(i){if(i instanceof e.PieSeries){o=i.get("categoryAxis"),o&&!(o instanceof e.Axis)&&i.set("categoryAxis",s[o]),o=i.get("valueAxis"),o&&!(o instanceof e.Axis)&&i.set("valueAxis",s[o]);continue}i.categoryAxis=s.category,i.valueAxis=s.values,i.type||(i.type=this.get("type"))}}},_getDefaultAxes:function(){var e=this.get("categoryKey"),t=this.get("seriesKeys").concat(),n="numeric";return{values:{keys:t,type:n},category:{keys:[e],type:this.get("categoryType")}}},getSeriesItems:function(e,t){var n={axis:e.get("categoryAxis"),key:e.get("categoryKey"),displayName:e.get("categoryDisplayName")},r={axis:e.get("valueAxis"),key:e.get("valueKey"),displayName:e.get("valueDisplayName")};return n.value=n.axis.getKeyValueAt(n.key,t),r.value=r.axis.getKeyValueAt(r.key,t),{category:n,value:r}},_sizeChanged:function(e){this._redraw()},_redraw:function(){var e=this.get("graph"),t=this.get("width"),n=this.get("height"),r;e&&(r=Math.min(t,n),e.set("width",r),e.set("height",r))},_tooltipLabelFunction:function(e,t,n,r,s){var o=i.createElement("div"),u=r.getTotalValues(),a=Math.round(t.value/u*1e4)/100;return o.appendChild(i.createTextNode(e.displayName+": "+e.axis.get("labelFunction").apply(this,[e.value,e.axis.get("labelFormat")]))),o.appendChild(i.createElement("br")),o.appendChild(i.createTextNode(t.displayName+": "+t.axis.get("labelFunction").apply(this,[t.value,t.axis.get("labelFormat")]))),o.appendChild(i.createElement("br")),o.appendChild(i.createTextNode(a+"%")),o},_getAriaMessage:function(e){var t="",n,r,i,s,o=0,u=this._itemIndex,a=this.get("seriesCollection"),f,l,c,h;return i=this.getSeries(parseInt(o,10)),h=i.get("markers"),f=h&&h.length?h.length:0,e===37?u=u>0?u-1:f-1:e===39&&(u=u>=f-1?0:u+1),this._itemIndex=u,r=this.getSeriesItems(i,u),n=r.category,s=r.value,l=i.getTotalValues(),c=Math.round(s.value/l*1e4)/100,n&&s?(t+=n.displayName+": "+n.axis.formatLabel.apply(this,[n.value,n.axis.get("labelFormat")])+", ",t+=s.displayName+": "+s.axis.formatLabel.apply(this,[s.value,s.axis.get("labelFormat")])+", ",t+="Percent of total "+s.displayName+": "+c+"%,"):t+="No data available,",t+=u+1+" of "+f+". ",t}},{ATTRS:{ariaDescription:{value:"Use the left and right keys to navigate through items.",setter:function(e){return this._description&&(this._description.setContent(""),this._description.appendChild(i.createTextNode(e))),e}},axes:{getter:function(){return this._axes},setter:function(e){this._parseAxes(e)}},seriesCollection:{getter:function(){return this._getSeriesCollection()},setter:function(e){return this._setSeriesCollection(e)}},type:{value:"pie"}}})},"3.7.3",{requires:["dom","datatype-number","datatype-date","event-custom","event-mouseenter","event-touch","widget","widget-position","widget-stack","graphics"]});
diff --git a/js/yui3/charts-legend/charts-legend-min.js b/js/yui3/charts-legend/charts-legend-min.js
new file mode 100644
index 000000000..4eb70accc
--- /dev/null
+++ b/js/yui3/charts-legend/charts-legend-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("charts-legend",function(e,t){function E(t){return t.type!="pie"?new e.CartesianChart(t):new e.PieChart(t)}var n=e.config.doc,r="top",i="right",s="bottom",o="left",u="external",a="horizontal",f="vertical",l="width",c="height",h="position",p="x",d="y",v="px",m={setter:function(t){var n=this.get("legend");return n&&n.destroy(!0),t instanceof e.ChartLegend?(n=t,n.set("chart",this)):(t.chart=this,t.hasOwnProperty("render")||(t.render=this.get("contentBox"),t.includeInChartLayout=!0),n=new e.ChartLegend(t)),n}},g={_positionLegendItems:function(e,t,n,r,i,s,o,u,a,f){var l=0,c=0,h,p,d,m,y,b=this.get("width"),w,E,S,x,T,N=s.top-u,C=b-(s.left+s.right),k,L,A,O;g._setRowArrays(e,C,o),w=g.rowArray,x=g.totalWidthArray,E=w.length;for(;c<E;++c){N+=u,S=w[c],y=S.length,T=g.getStartPoint(b,x[c],a,s);for(l=0;l<y;++l)h=S[l],p=h.node,d=h.width,m=h.height,h.x=T,h.y=0,k=isNaN(k)?T:Math.min(k,T),L=isNaN(L)?N:Math.min(L,N),A=isNaN(A)?T+d:Math.max(T+d,A),O=isNaN(O)?N+m:Math.max(N+m,O),p.setStyle("left",T+v),p.setStyle("top",N+v),T+=d+o;N+=h.height}this._contentRect={left:k,top:L,right:A,bottom:O},this.get("includeInChartLayout")&&this.set("height",N+s.bottom)},_setRowArrays:function(e,t,n){var r=e[0],i=[[r]],s=1,o=0,u=e.length,a=r.width,f,l=[[a]];for(;s<u;++s)r=e[s],f=r.width,a+n+f<=t?(a+=n+f,i[o].push(r)):(a=n+f,i[o]&&(o+=1),i[o]=[r]),l[o]=a;g.rowArray=i,g.totalWidthArray=l},getStartPoint:function(e,t,n,r){var s;switch(n){case o:s=r.left;break;case"center":s=(e-t)*.5;break;case i:s=e-t-r.right}return s}},y={_positionLegendItems:function(e,t,n,r,i,s,o,u,a,f){var l=0,c=0,h,p,d,m,g,b=this.get("height"),w,E,S,x,T,N=s.left-o,C,k=b-(s.top+s.bottom),L,A,O,M;y._setColumnArrays(e,k,u),w=y.columnArray,x=y.totalHeightArray,E=w.length;for(;c<E;++c){N+=o,S=w[c],g=S.length,T=y.getStartPoint(b,x[c],f,s),C=0;for(l=0;l<g;++l)h=S[l],p=h.node,d=h.height,m=h.width,h.y=T,h.x=N,L=isNaN(L)?N:Math.min(L,N),A=isNaN(A)?T:Math.min(A,T),O=isNaN(O)?N+m:Math.max(N+m,O),M=isNaN(M)?T+d:Math.max(T+d,M),p.setStyle("left",N+v),p.setStyle("top",T+v),T+=d+u,C=Math.max(C,h.width);N+=C}this._contentRect={left:L,top:A,right:O,bottom:M},this.get("includeInChartLayout")&&this.set("width",N+s.right)},_setColumnArrays:function(e,t,n){var r=e[0],i=[[r]],s=1,o=0,u=e.length,a=r.height,f,l=[[a]];for(;s<u;++s)r=e[s],f=r.height,a+n+f<=t?(a+=n+f,i[o].push(r)):(a=n+f,i[o]&&(o+=1),i[o]=[r]),l[o]=a;y.columnArray=i,y.totalHeightArray=l},getStartPoint:function(e,t,n,i){var o;switch(n){case r:o=i.top;break;case"middle":o=(e-t)*.5;break;case s:o=e-t-i.bottom}return o}},b=e.Base.create("cartesianChartLegend",e.CartesianChart,[],{_redraw:function(){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1;var e=this.get("width"),t=this.get("height"),n=this._getLayoutBoxDimensions(),r=n.left,i=n.right,s=n.top,o=n.bottom,u=this.get("leftAxesCollection"),a=this.get("rightAxesCollection"),f=this.get("topAxesCollection"),l=this.get("bottomAxesCollection"),c=0,h,p,d="visible",m=this.get("graph"),g,y,b,w,E,S,x,T,N=this.get("allowContentOverflow"),C,k,L,A,O,M=this.get("legend"),_={};if(u){L=[],h=u.length;for(c=h-1;c>-1;--c)L.unshift(r),r+=u[c].get("width")}if(a){k=[],h=a.length,c=0;for(c=h-1;c>-1;--c)i+=a[c].get("width"),k.unshift(e-i)}if(f){A=[],h=f.length;for(c=h-1;c>-1;--c)A.unshift(s),s+=f[c].get("height")}if(l){O=[],h=l.length;for(c=h-1;c>-1;--c)o+=l[c].get("height"),O.unshift(t-o)}E=e-(r+i),S=t-(o+s),_.left=r,_.top=s,_.bottom=t-o,_.right=e-i;if(!N){g=this._getTopOverflow(u,a),y=this._getBottomOverflow(u,a),b=this._getLeftOverflow(l,f),w=this._getRightOverflow(l,f),C=g-s;if(C>0){_.top=g;if(A){c=0,h=A.length;for(;c<h;++c)A[c]+=C}}C=y-o;if(C>0){_.bottom=t-y;if(O){c=0,h=O.length;for(;c<h;++c)O[c]-=C}}C=b-r;if(C>0){_.left=b;if(L){c=0,h=L.length;for(;c<h;++c)L[c]+=C}}C=w-i;if(C>0){_.right=e-w;if(k){c=0,h=k.length;for(;c<h;++c)k[c]-=C}}}E=_.right-_.left,S=_.bottom-_.top,x=_.left,T=_.top;if(M&&M.get("includeInChartLayout"))switch(M.get("position")){case"left":M.set("y",T),M.set("height",S);break;case"top":M.set("x",x),M.set("width",E);break;case"bottom":M.set("x",x),M.set("width",E);break;case"right":M.set("y",T),M.set("height",S)}if(f){h=f.length,c=0;for(;c<h;c++)p=f[c],p.get("width")!==E&&p.set("width",E),p.get("boundingBox").setStyle("left",x+v),p.get("boundingBox").setStyle("top",A[c]+v);p._hasDataOverflow()&&(d="hidden")}if(l){h=l.length,c=0;for(;c<h;c++)p=l[c],p.get("width")!==E&&p.set("width",E),p.get("boundingBox").setStyle("left",x+v),p.get("boundingBox").setStyle("top",O[c]+v);p._hasDataOverflow()&&(d="hidden")}if(u){h=u.length,c=0;for(;c<h;++c)p=u[c],p.get("boundingBox").setStyle("top",T+v),p.get("boundingBox").setStyle("left",L[c]+v),p.get("height")!==S&&p.set("height",S);p._hasDataOverflow()&&(d="hidden")}if(a){h=a.length,c=0;for(;c<h;++c)p=a[c],p.get("boundingBox").setStyle("top",T+v),p.get("boundingBox").setStyle("left",k[c]+v),p.get("height")!==S&&p.set("height",S);p._hasDataOverflow()&&(d="hidden")}this._drawing=!1;if(this._callLater){this._redraw();return}m&&(m.get("boundingBox").setStyle("left",x+v),m.get("boundingBox").setStyle("top",T+v),m.set("width",E),m.set("height",S),m.get("boundingBox").setStyle("overflow",d)),this._overlay&&(this._overlay.setStyle("left",x+v),this._overlay.setStyle("top",T+v),this._overlay.setStyle("width",E+v),this._overlay.setStyle("height",S+v))},_getLayoutBoxDimensions:function(){var e={top:0,right:0,bottom:0,left:0},t=this.get("legend"),n,f,v,m,g=this.get(l),y=this.get(c),b;if(t&&t.get("includeInChartLayout")){b=t.get("styles").gap,n=t.get(h);if(n!=u){f=t.get("direction"),v=f==a?c:l,m=t.get(v),e[n]=m+b;switch(n){case r:t.set(d,0);break;case s:t.set(d,y-m);break;case i:t.set(p,g-m);break;case o:t.set(p,0)}}}return e},destructor:function(){var e=this.get("legend");e&&e.destroy(!0)}},{ATTRS:{legend:m}});e.CartesianChart=b;var w=e.Base.create("pieChartLegend",e.PieChart,[],{_redraw:function(){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1;var e=this.get("graph"),t=this.get("width"),n=this.get("height"),u,a,f=this.get("legend"),h=0,v=0,m=0,g=0,y,b,w,E,S,x;if(e)if(f){S=f.get("position"),x=f.get("direction"),u=e.get("width"),a=e.get("height"),y=f.get("width"),b=f.get("height"),E=f.get("styles").gap;if(x=="vertical"&&u+y+E!==t||x=="horizontal"&&a+b+E!==n){switch(f.get("position")){case o:w=Math.min(t-(y+E),n),b=n,h=y+E,f.set(c,b);break;case r:w=Math.min(n-(b+E),t),y=t,v=b+E,f.set(l,y);break;case i:w=Math.min(t-(y+E),n),b=n,m=w+E,f.set(c,b);break;case s:w=Math.min(n-(b+E),t),y=t,g=w+E,f.set(l,y)}e.set(l,w),e.set(c,w)}else switch(f.get("position")){case o:h=y+E;break;case r:v=b+E;break;case i:m=u+E;break;case s:g=a+E}}else e.set(p,0),e.set(d,0),e.set(l,t),e.set(c,n);this._drawing=!1;if(this._callLater){this._redraw();return}e&&(e.set(p,h),e.set(d,v)),f&&(f.set(p,m),f.set(d,g))}},{ATTRS:{legend:m}});e.PieChart=w,e.ChartLegend=e.Base.create("chartlegend",e.Widget,[e.Renderer],{initializer:function(){this._items=[]},renderUI:function(){var t=this.get("boundingBox"),n=this.get("contentBox"),r=this.get("styles").background,i=new e.Rect({graphic:n,fill:r.fill,stroke:r.border});t.setStyle("display","block"),t.setStyle("position","absolute"),this.set("background",i)},bindUI:function(){this.get("chart").after("seriesCollectionChange",e.bind(this._updateHandler,this)),this.after("stylesChange",this._updateHandler),this.after("positionChange",this._positionChangeHandler),this.after("widthChange",this._handleSizeChange),this.after("heightChange",this._handleSizeChange)},syncUI:function(){var e=this.get("width"),t=this.get("height");isFinite(e)&&isFinite(t)&&e>0&&t>0&&this._drawLegend()},_updateHandler:function(e){this.get("rendered")&&this._drawLegend()},_positionChangeHandler:function(e){var t=this.get("chart"),n=this._parentNode;n&&t&&this.get("includeInChartLayout")?this.fire("legendRendered"):this.get("rendered")&&this._drawLegend()},_handleSizeChange:function(e){var t=e.attrName,n=this.get(h),u=n==o||n==i,a=n==s||n==r;(a&&t==l||u&&t==c)&&this._drawLegend()},_drawLegend:function(){if(this._drawing){this._callLater=!0;return}this._drawing=!0,this._callLater=!1,this.get("includeInChartLayout")&&this.get("chart")._itemRenderQueue.unshift(this);var t=this.get("chart"),n=this.get("contentBox"),r=t.get("seriesCollection"),i,s=this.get("styles"),o=s.padding,u=s.item,a,f=u.hSpacing,l=u.vSpacing,c=s.hAlign,h=s.vAlign,p=s.marker,d=u.label,v,m=this._layout[this.get("direction")],g,y,b,w,E,S,x,T,N,C,k,L=[],A=p.width,O=p.height,M=0-f,_=0-l,D=0,P=0,H,B;p&&p.shape&&(w=p.shape),this._destroyLegendItems();if(t instanceof e.PieChart){i=r[0],v=i.get("categoryAxis").getDataByKey(i.get("categoryKey")),a=i.get("styles").marker,N=a.fill.colors,C=a.border.colors,k=a.border.weight,g=0,y=v.length,w=w||e.Circle,b=e.Lang.isArray(w);for(;g<y;++g)w=b?w[g]:w,x={color:N[g]},T={colors:C[g],weight:k},v=t.getSeriesItems(i,g).category.value,S=this._getLegendItem(n,this._getShapeClass(w),x,T,d,A,O,v),H=S.width,B=S.height,D=Math.max(D,H),P=Math.max(P,B),M+=H+f,_+=B+l,L.push(S)}else{g=0,y=r.length;for(;g<y;++g)i=r[g],a=this._getStylesBySeriesType(i,w),w||(w=a.shape,w||(w=e.Circle)),E=e.Lang.isArray(w)?w[g]:w,S=this._getLegendItem(n,this._getShapeClass(w),a.fill,a.border,d,A,O,i.get("valueDisplayName")),H=S.width,B=S.height,D=Math.max(D,H),P=Math.max(P,B),M+=H+f,_+=B+l,L.push(S)}this._drawing=!1,this._callLater?this._drawLegend():(m._positionLegendItems.apply(this,[L,D,P,M,_,o,f,l,c,h]),this._updateBackground(s),this.fire("legendRendered"))},_updateBackground:function(e){var t=e.background,n=this._contentRect,r=e.padding,i=n.left-r.left,s=n.top-r.top,o=n.right-i+r.right,u=n.bottom-s+r.bottom;this.get("background").set({fill:t.fill,stroke:t.border,width:o,height:u,x:i,y:s})},_getStylesBySeriesType:function(t){var n=t.get("styles"),r;return t instanceof e.LineSeries||t instanceof e.StackedLineSeries?(n=t.get("styles").line,r=n.color||t._getDefaultColor(t.get("graphOrder"),"line"),{border:{weight:1,color:r},fill:{color:r}}):t instanceof e.AreaSeries||t instanceof e.StackedAreaSeries?(n=t.get("styles").area,r=n.color||t._getDefaultColor(t.get("graphOrder"),"slice"),{border:{weight:1,color:r},fill:{color:r}}):(n=t.get("styles").marker,{fill:n.fill,border:{weight:n.border.weight,color:n.border.color,shape:n.shape},shape:n.shape})},_getLegendItem:function(t,r,i,s,o,u,a,f){var l=e.one(n.createElement("div")),c=e.one(n.createElement("span")),p,d,m,g,y;return l.setStyle(h,"absolute"),c.setStyle(h,"absolute"),c.setStyles(o),c.appendChild(n.createTextNode(f)),l.appendChild(c),t.appendChild(l),d=c.get("offsetHeight"),m=d-a,g=u+m+2,c.setStyle("left",g+v),l.setStyle("height",d+v),l.setStyle("width",g+c.get("offsetWidth")+v),p=new r({fill:i,stroke:s,width:u,height:a,x:m*.5,y:m*.5,w:u,h:a,graphic:l}),c.setStyle("left",d+v),y={node:l,width:l.get("offsetWidth"),height:l.get("offsetHeight"),shape:p,textNode:c,text:f},this._items.push(y),y},_getShapeClass:function(){var e=this.get("background").get("graphic");return e._getShapeClass.apply(e,arguments)},_getDefaultStyles:function(){var e={padding:{top:8,right:8,bottom:8,left:9},gap:10,hAlign:"center",vAlign:"top",marker:this._getPlotDefaults(),item:{hSpacing:10,vSpacing:5,label:{color:"#808080",fontSize:"85%",whiteSpace:"nowrap"}},background:{shape:"rect",fill:{color:"#faf9f2"},border:{color:"#dad8c9",weight:1}}};return e},_getPlotDefaults:function(){var e={width:10,height:10};return e},_destroyLegendItems:function(){var e;if(this._items)while(this._items.length>0)e=this._items.shift(),e.shape.get("graphic").destroy(),e.node.empty(),e.node.destroy(!0),e.node=null,e=null;this._items=[]},_layout:{vertical:y,horizontal:g},destructor:function(){var e=this.get("background"),t;this._destroyLegendItems(),e&&(t=e.get("graphic"),t?t.destroy():e.destroy())}},{ATTRS:{includeInChartLayout:{value:!1},chart:{setter:function(t){return this.after("legendRendered",e.bind(t._itemRendered,t)),t}},direction:{value:"vertical"},position:{lazyAdd:!1,value:"right",setter:function(e){return e==r||e==s?this.set("direction",a):(e==o||e==i)&&this.set("direction",f),e}},width:{getter:function(){var e=this.get("chart"),t=this._parentNode;return t?e&&this.get("includeInChartLayout")||this._width?(this._width||(this._width=0),this._width):t.get("offsetWidth"):""},setter:function(e){return this._width=e,e}},height:{valueFn:"_heightGetter",getter:function(){var e=this.get("chart"),t=this._parentNode;return t?e&&this.get("includeInChartLayout")||this._height?(this._height||(this._height=0),this._height):t.get("offsetHeight"):""},setter:function(e){return this._height=e,e}},x:{lazyAdd:!1,value:0,setter:function(e){var t=this.get("boundingBox");return t&&t.setStyle(o,e+v),e}},y:{lazyAdd:!1,value:0,setter:function(e){var t=this.get("boundingBox");return t&&t.setStyle(r,e+v),e}},items:{getter:function(){return this._items}},background:{}}}),e.Chart=E},"3.7.3",{requires:["charts-base"]});
diff --git a/js/yui3/charts/charts-min.js b/js/yui3/charts/charts-min.js
new file mode 100644
index 000000000..9cad7e5bd
--- /dev/null
+++ b/js/yui3/charts/charts-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("charts",function(e,t){function n(t){return t.type!="pie"?new e.CartesianChart(t):new e.PieChart(t)}e.Chart=n},"3.7.3",{requires:["charts-base"]});
diff --git a/js/yui3/classnamemanager/classnamemanager-min.js b/js/yui3/classnamemanager/classnamemanager-min.js
new file mode 100644
index 000000000..336ffc0b4
--- /dev/null
+++ b/js/yui3/classnamemanager/classnamemanager-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("classnamemanager",function(e,t){var n="classNamePrefix",r="classNameDelimiter",i=e.config;i[n]=i[n]||"yui3",i[r]=i[r]||"-",e.ClassNameManager=function(){var t=i[n],s=i[r];return{getClassName:e.cached(function(){var n=e.Array(arguments);return n[n.length-1]!==!0?n.unshift(t):n.pop(),n.join(s)})}}()},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/clickable-rail/assets/slider-base-core.css b/js/yui3/clickable-rail/assets/slider-base-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/slider-base-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/clickable-rail/assets/slider-core.css b/js/yui3/clickable-rail/assets/slider-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/slider-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/clickable-rail/assets/thumb-x-oblong-dark.png b/js/yui3/clickable-rail/assets/thumb-x-oblong-dark.png
new file mode 100644
index 000000000..bc0aa14ce
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-x-oblong-dark.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-x-oblong.png b/js/yui3/clickable-rail/assets/thumb-x-oblong.png
new file mode 100644
index 000000000..670ba1ea1
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-x-oblong.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-x-oblong2-dark.png b/js/yui3/clickable-rail/assets/thumb-x-oblong2-dark.png
new file mode 100644
index 000000000..20f126029
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-x-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-x-oblong2.png b/js/yui3/clickable-rail/assets/thumb-x-oblong2.png
new file mode 100644
index 000000000..76e34e60a
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-x-oblong2.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-y-oblong-dark.png b/js/yui3/clickable-rail/assets/thumb-y-oblong-dark.png
new file mode 100644
index 000000000..a0eed7087
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-y-oblong-dark.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-y-oblong.png b/js/yui3/clickable-rail/assets/thumb-y-oblong.png
new file mode 100644
index 000000000..e63c8d7d8
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-y-oblong.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-y-oblong2-dark.png b/js/yui3/clickable-rail/assets/thumb-y-oblong2-dark.png
new file mode 100644
index 000000000..e91ffb7b3
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-y-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/clickable-rail/assets/thumb-y-oblong2.png b/js/yui3/clickable-rail/assets/thumb-y-oblong2.png
new file mode 100644
index 000000000..89a466727
--- /dev/null
+++ b/js/yui3/clickable-rail/assets/thumb-y-oblong2.png
Binary files differ
diff --git a/js/yui3/clickable-rail/clickable-rail-min.js b/js/yui3/clickable-rail/clickable-rail-min.js
new file mode 100644
index 000000000..28240d7c1
--- /dev/null
+++ b/js/yui3/clickable-rail/clickable-rail-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("clickable-rail",function(e,t){function n(){this._initClickableRail()}e.ClickableRail=e.mix(n,{prototype:{_initClickableRail:function(){this._evtGuid=this._evtGuid||e.guid()+"|",this.publish("railMouseDown",{defaultFn:this._defRailMouseDownFn}),this.after("render",this._bindClickableRail),this.on("destroy",this._unbindClickableRail)},_bindClickableRail:function(){this._dd.addHandle(this.rail),this.rail.on(this._evtGuid+e.DD.Drag.START_EVENT,e.bind(this._onRailMouseDown,this))},_unbindClickableRail:function(){if(this.get("rendered")){var e=this.get("contentBox"),t=e.one("."+this.getClassName("rail"));t.detach(this.evtGuid+"*")}},_onRailMouseDown:function(e){this.get("clickableRail")&&!this.get("disabled")&&(this.fire("railMouseDown",{ev:e}),this.thumb.focus())},_defRailMouseDownFn:function(e){e=e.ev;var t=this._resolveThumb(e),n=this._key.xyIndex,r=parseFloat(this.get("length"),10),i,s,o;t&&(i=t.get("dragNode"),s=parseFloat(i.getStyle(this._key.dim),10),o=this._getThumbDestination(e,i),o=o[n]-this.rail.getXY()[n],o=Math.min(Math.max(o,0),r-s),this._uiMoveThumb(o,{source:"rail"}),e.target=this.thumb.one("img")||this.thumb,t._handleMouseDownEvent(e))},_resolveThumb:function(e){return this._dd},_getThumbDestination:function(e,t){var n=t.get("offsetWidth"),r=t.get("offsetHeight");return[e.pageX-Math.round(n/2),e.pageY-Math.round(r/2)]}},ATTRS:{clickableRail:{value:!0,validator:e.Lang.isBoolean}}},!0)},"3.7.3",{requires:["slider-base"]});
diff --git a/js/yui3/console-filters/assets/console-filters-core.css b/js/yui3/console-filters/assets/console-filters-core.css
new file mode 100644
index 000000000..ab590e648
--- /dev/null
+++ b/js/yui3/console-filters/assets/console-filters-core.css
@@ -0,0 +1,6 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
diff --git a/js/yui3/console-filters/assets/skins/sam/console-filters.css b/js/yui3/console-filters/assets/skins/sam/console-filters.css
new file mode 100644
index 000000000..69b6a580d
--- /dev/null
+++ b/js/yui3/console-filters/assets/skins/sam/console-filters.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{text-align:left;padding:5px 0;border:1px inset;margin:0 2px}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories{background:#fff;border-bottom:2px ridge}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{background:#fff;margin-bottom:2px;border-top:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-filter-label{white-space:nowrap;margin-left:1ex}#yui3-css-stamp.skin-sam-console-filters{display:none}
diff --git a/js/yui3/console-filters/console-filters-min.js b/js/yui3/console-filters/console-filters-min.js
new file mode 100644
index 000000000..598e85145
--- /dev/null
+++ b/js/yui3/console-filters/console-filters-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("console-filters",function(e,t){function b(){b.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="console",i="filters",s="filter",o="category",u="source",a="category.",f="source.",l="host",c="checked",h="defaultVisibility",p=".",d="",v=p+e.Console.CHROME_CLASSES.console_bd_class,m=p+e.Console.CHROME_CLASSES.console_ft_class,g="input[type=checkbox].",y=e.Lang.isString;e.namespace("Plugin").ConsoleFilters=e.extend(b,e.Plugin.Base,{_entries:null,_cacheLimit:Number.POSITIVE_INFINITY,_categories:null,_sources:null,initializer:function(){this._entries=[],this.get(l).on("entry",this._onEntry,this),this.doAfter("renderUI",this.renderUI),this.doAfter("syncUI",this.syncUI),this.doAfter("bindUI",this.bindUI),this.doAfter("clearConsole",this._afterClearConsole),this.get(l).get("rendered")&&(this.renderUI(),this.syncUI(),this.bindUI()),this.after("cacheLimitChange",this._afterCacheLimitChange)},destructor:function(){this._entries=[],this._categories&&this._categories.remove(),this._sources&&this._sources.remove()},renderUI:function(){var t=this.get(l).get("contentBox").one(m),n;t&&(n=e.Lang.sub(b.CATEGORIES_TEMPLATE,b.CHROME_CLASSES),this._categories=t.appendChild(e.Node.create(n)),n=e.Lang.sub(b.SOURCES_TEMPLATE,b.CHROME_CLASSES),this._sources=t.appendChild(e.Node.create(n)))},bindUI:function(){this._categories.on("click",e.bind(this._onCategoryCheckboxClick,this)),this._sources.on("click",e.bind(this._onSourceCheckboxClick,this)),this.after("categoryChange",this._afterCategoryChange),this.after("sourceChange",this._afterSourceChange)},syncUI:function(){e.each(this.get(o),function(e,t){this._uiSetCheckbox(o,t,e)},this),e.each(this.get(u),function(e,t){this._uiSetCheckbox(u,t,e)},this),this.refreshConsole()},_onEntry:function(e){this._entries.push(e.message);var t=a+e.message.category,n=f+e.message.source,r=this.get(t),i=this.get(n),s=this._entries.length-this._cacheLimit,o;s>0&&this._entries.splice(0,s),r===undefined&&(o=this.get(h),this.set(t,o),r=o),i===undefined&&(o=this.get(h),this.set(n,o),i=o),(!r||!i)&&e.preventDefault()},_afterClearConsole:function(){this._entries=[]},_afterCategoryChange:function(e){var t=e.subAttrName.replace(/category\./,d),n=e.prevVal,r=e.newVal;if(!t||n[t]!==undefined)this.refreshConsole(),this._filterBuffer();t&&!e.fromUI&&this._uiSetCheckbox(o,t,r[t])},_afterSourceChange:function(e){var t=e.subAttrName.replace(/source\./,d),n=e.prevVal,r=e.newVal;if(!t||n[t]!==undefined)this.refreshConsole(),this._filterBuffer();t&&!e.fromUI&&this._uiSetCheckbox(u,t,r[t])},_filterBuffer:function(){var e=this.get(o),t=this.get(u),n=this.get(l).buffer,r=null,i;for(i=n.length-1;i>=0;--i)!e[n[i].category]||!t[n[i].source]?r=r||i:r&&(n.splice(i,r-i),r=null);r&&n.splice(0,r+1)},_afterCacheLimitChange:function(e){if(isFinite(e.newVal)){var t=this._entries.length-e.newVal;t>0&&this._entries.splice(0,t)}},refreshConsole:function(){var e=this._entries,t=this.get(l),n=t.get("contentBox").one(v),r=t.get("consoleLimit"),i=this.get(o),s=this.get(u),a=[],f,c;if(n){t._cancelPrintLoop();for(f=e.length-1;f>=0&&r>=0;--f)c=e[f],i[c.category]&&s[c.source]&&(a.unshift(c),--r);n.setHTML(d),t.buffer=a,t.printBuffer()}},_uiSetCheckbox:function(e,t,i){if(e&&t){var u=e===o?this._categories:this._sources,a=g+n(r,s,t),f=u.one(a),h;f||(h=this.get(l),this._createCheckbox(u,t),f=u.one(a),h._uiSetHeight(h.get("height"))),f.set(c,i)}},_onCategoryCheckboxClick:function(e){var t=e.target,n;t.hasClass(b.CHROME_CLASSES.filter)&&(n=t.get("value"),n&&n in this.get(o)&&this.set(a+n,t.get(c),{fromUI:!0}))},_onSourceCheckboxClick:function(e){var t=e.target,n;t.hasClass(b.CHROME_CLASSES.filter)&&(n=t.get("value"),n&&n in this.get(u)&&this.set(f+n,t.get(c),{fromUI:!0}))},hideCategory:function(t,n){y(n)?e.Array.each(arguments,this.hideCategory,this):this.set(a+t,!1)},showCategory:function(t,n){y(n)?e.Array.each(arguments,this.showCategory,this):this.set(a+t,!0)},hideSource:function(t,n){y(n)?e.Array.each(arguments,this.hideSource,this):this.set(f+t,!1)},showSource:function(t,n){y(n)?e.Array.each(arguments,this.showSource,this):this.set(f+t,!0)},_createCheckbox:function(t,i){var o=e.merge(b.CHROME_CLASSES,{filter_name:i,filter_class:n(r,s,i)}),u=e.Node.create(e.Lang.sub(b.FILTER_TEMPLATE,o));t.appendChild(u)},_validateCategory:function(t,n){return e.Lang.isObject(n,!0)&&t.split(/\./).length<3},_validateSource:function(t,n){return e.Lang.isObject(n,!0)&&t.split(/\./).length<3},_setCacheLimit:function(t){return e.Lang.isNumber(t)?(this._cacheLimit=t,t):e.Attribute.INVALID_VALUE}},{NAME:"consoleFilters",NS:s,CATEGORIES_TEMPLATE:'<div class="{categories}"></div>',SOURCES_TEMPLATE:'<div class="{sources}"></div>',FILTER_TEMPLATE:'<label class="{filter_label}"><input type="checkbox" value="{filter_name}" class="{filter} {filter_class}"> {filter_name}</label>&#8201;',CHROME_CLASSES:{categories:n(r,i,"categories"),sources:n(r,i,"sources"),category:n(r,s,o),source:n(r,s,u),filter:n(r,s),filter_label:n(r,s,"label")},ATTRS:{defaultVisibility:{value:!0,validator:e.Lang.isBoolean},category:{value:{},validator:function(e,t){return this._validateCategory(t,e)}},source:{value:{},validator:function(e,t){return this._validateSource(t,e)}},cacheLimit:{value:Number.POSITIVE_INFINITY,setter:function(e){return this._setCacheLimit(e)}}}})},"3.7.3",{requires:["plugin","console"],skinnable:!0});
diff --git a/js/yui3/console/assets/console-core.css b/js/yui3/console/assets/console-core.css
new file mode 100644
index 000000000..ab590e648
--- /dev/null
+++ b/js/yui3/console/assets/console-core.css
@@ -0,0 +1,6 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
diff --git a/js/yui3/console/assets/console-filters-core.css b/js/yui3/console/assets/console-filters-core.css
new file mode 100644
index 000000000..ab590e648
--- /dev/null
+++ b/js/yui3/console/assets/console-filters-core.css
@@ -0,0 +1,6 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
diff --git a/js/yui3/console/assets/skins/sam/bg.png b/js/yui3/console/assets/skins/sam/bg.png
new file mode 100644
index 000000000..fd11e03de
--- /dev/null
+++ b/js/yui3/console/assets/skins/sam/bg.png
Binary files differ
diff --git a/js/yui3/console/assets/skins/sam/console-filters.css b/js/yui3/console/assets/skins/sam/console-filters.css
new file mode 100644
index 000000000..48f867b7d
--- /dev/null
+++ b/js/yui3/console/assets/skins/sam/console-filters.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{text-align:left;padding:5px 0;border:1px inset;margin:0 2px;}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-categories{background:#fff;border-bottom:2px ridge;}.yui3-skin-sam .yui3-console-ft .yui3-console-filters-sources{background:#fff;margin-bottom:2px;border-top:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px;}.yui3-skin-sam .yui3-console-filter-label{white-space:nowrap;margin-left:1ex;}
diff --git a/js/yui3/console/assets/skins/sam/console.css b/js/yui3/console/assets/skins/sam/console.css
new file mode 100644
index 000000000..5374c653e
--- /dev/null
+++ b/js/yui3/console/assets/skins/sam/console.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-console-separate{position:absolute;right:1em;top:1em;z-index:999}.yui3-skin-sam .yui3-console-inline{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:top}.yui3-skin-sam .yui3-console-inline .yui3-console-content{position:relative}.yui3-skin-sam .yui3-console-content{background:#777;_background:#d8d8da url(bg.png) repeat-x 0 0;font:normal 13px/1.3 Arial,sans-serif;text-align:left;border:1px solid #777;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-bd,.yui3-skin-sam .yui3-console-ft{position:relative}.yui3-skin-sam .yui3-console-hd,.yui3-skin-sam .yui3-console-ft .yui3-console-controls{text-align:right}.yui3-skin-sam .yui3-console-hd{background:#d8d8da url(bg.png) repeat-x 0 0;padding:1ex;border:1px solid transparent;_border:0 none;border-top-right-radius:10px;border-top-left-radius:10px;-moz-border-radius-topright:10px;-moz-border-radius-topleft:10px;-webkit-border-top-right-radius:10px;-webkit-border-top-left-radius:10px}.yui3-skin-sam .yui3-console-bd{background:#fff;border-top:1px solid #777;border-bottom:1px solid #777;color:#000;font-size:11px;overflow:auto;overflow-x:auto;overflow-y:scroll;_width:100%}.yui3-skin-sam .yui3-console-ft{background:#d8d8da url(bg.png) repeat-x 0 0;border:1px solid transparent;_border:0 none;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px;-webkit-border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px}.yui3-skin-sam .yui3-console-controls{padding:4px 1ex;zoom:1}.yui3-skin-sam .yui3-console-title{color:#000;display:inline;float:left;font-weight:bold;font-size:13px;height:24px;line-height:24px;margin:0;padding-left:1ex}.yui3-skin-sam .yui3-console-pause-label{float:left}.yui3-skin-sam .yui3-console-button{line-height:1.3}.yui3-skin-sam .yui3-console-collapsed .yui3-console-bd,.yui3-skin-sam .yui3-console-collapsed .yui3-console-ft{display:none}.yui3-skin-sam .yui3-console-content.yui3-console-collapsed{-webkit-border-radius:0}.yui3-skin-sam .yui3-console-collapsed .yui3-console-hd{border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:0}.yui3-skin-sam .yui3-console-entry{border-bottom:1px solid #aaa;min-height:32px;_height:32px}.yui3-skin-sam .yui3-console-entry-meta{margin:0;overflow:hidden}.yui3-skin-sam .yui3-console-entry-content{margin:0;padding:0 1ex;white-space:pre-wrap;word-wrap:break-word}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-src{color:#000;font-style:italic;font-weight:bold;float:right;margin:2px 5px 0 0}.yui3-skin-sam .yui3-console-entry-meta .yui3-console-entry-time{color:#777;padding-left:1ex}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-time{color:#555}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-meta .yui3-console-entry-cat,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-meta .yui3-console-entry-cat{display:none}.yui3-skin-sam .yui3-console-entry-warn{background:#aee url(warn_error.png) no-repeat -15px 15px}.yui3-skin-sam .yui3-console-entry-error{background:#ffa url(warn_error.png) no-repeat 5px -24px;color:#900}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-content,.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-content{padding-left:24px}.yui3-skin-sam .yui3-console-entry-cat{text-transform:uppercase;padding:1px 4px;background-color:#ccc}.yui3-skin-sam .yui3-console-entry-info .yui3-console-entry-cat{background-color:#ac2}.yui3-skin-sam .yui3-console-entry-warn .yui3-console-entry-cat{background-color:#e81}.yui3-skin-sam .yui3-console-entry-error .yui3-console-entry-cat{background-color:#b00;color:#fff}.yui3-skin-sam .yui3-console-hidden{display:none}#yui3-css-stamp.skin-sam-console{display:none}
diff --git a/js/yui3/console/assets/skins/sam/warn_error.png b/js/yui3/console/assets/skins/sam/warn_error.png
new file mode 100644
index 000000000..8b0db799e
--- /dev/null
+++ b/js/yui3/console/assets/skins/sam/warn_error.png
Binary files differ
diff --git a/js/yui3/console/assets/warn_error.png b/js/yui3/console/assets/warn_error.png
new file mode 100644
index 000000000..8b0db799e
--- /dev/null
+++ b/js/yui3/console/assets/warn_error.png
Binary files differ
diff --git a/js/yui3/console/console-min.js b/js/yui3/console/console-min.js
new file mode 100644
index 000000000..ebd26a05e
--- /dev/null
+++ b/js/yui3/console/console-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("console",function(e,t){function et(){et.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="checked",i="clear",s="click",o="collapsed",u="console",a="contentBox",f="disabled",l="entry",c="error",h="height",p="info",d="lastTime",v="pause",m="paused",g="reset",y="startTime",b="title",w="warn",E=".",S=n(u,"button"),x=n(u,"checkbox"),T=n(u,i),N=n(u,"collapse"),C=n(u,o),k=n(u,"controls"),L=n(u,"hd"),A=n(u,"bd"),O=n(u,"ft"),M=n(u,b),_=n(u,l),D=n(u,l,"cat"),P=n(u,l,"content"),H=n(u,l,"meta"),B=n(u,l,"src"),j=n(u,l,"time"),F=n(u,v),I=n(u,v,"label"),q=/^(\S+)\s/,R=/&(?!#?[a-z0-9]+;)/g,U=/>/g,z=/</g,W="&#38;",X="&#62;",V="&#60;",$='<div class="{entry_class} {cat_class} {src_class}"><p class="{entry_meta_class}"><span class="{entry_src_class}">{sourceAndDetail}</span><span class="{entry_cat_class}">{category}</span><span class="{entry_time_class}"> {totalTime}ms (+{elapsedTime}) {localTime}</span></p><pre class="{entry_content_class}">{message}</pre></div>',J=e.Lang,K=e.Node.create,Q=J.isNumber,G=J.isString,Y=e.merge,Z=e.Lang.sub;e.Console=e.extend(et,e.Widget,{_evtCat:null,_head:null,_body:null,_foot:null,_printLoop:null,buffer:null,log:function(){return e.log.apply(e,arguments),this},clearConsole:function(){return this._body.empty(),this._cancelPrintLoop(),this.buffer=[],this},reset:function(){return this.fire(g),this},collapse:function(){return this.set(o,!0),this},expand:function(){return this.set(o,!1),this},printBuffer:function(t){var n=this.buffer,r=e.config.debug,i=[],s=this.get("consoleLimit"),o=this.get("newestOnTop"),u=o?this._body.get("firstChild"):null,a;n.length>s&&n.splice(0,n.length-s),t=Math.min(n.length,t||n.length),e.config.debug=!1;if(!this.get(m)&&this.get("rendered")){for(a=0;a<t&&n.length;++a)i[a]=this._createEntryHTML(n.shift());n.length||this._cancelPrintLoop(),i.length&&(o&&i.reverse(),this._body.insertBefore(K(i.join("")),u),this.get("scrollIntoView")&&this.scrollToLatest(),this._trimOldEntries())}return e.config.debug=r,this},initializer:function(){this._evtCat=e.stamp(this)+"|",this.buffer=[],this.get("logSource").on(this._evtCat+this.get("logEvent"),e.bind("_onLogEvent",this)),this.publish(l,{defaultFn:this._defEntryFn}),this.publish(g,{defaultFn:this._defResetFn}),this.after("rendered",this._schedulePrint)},destructor:function(){var e=this.get("boundingBox");this._cancelPrintLoop(),this.get("logSource").detach(this._evtCat+"*"),e.purge(!0)},renderUI:function(){this._initHead(),this._initBody(),this._initFoot();var e=this.get("style");e!=="block"&&this.get("boundingBox").addClass(this.getClassName(e))},syncUI:function(){this._uiUpdatePaused(this.get(m)),this._uiUpdateCollapsed(this.get(o)),this._uiSetHeight(this.get(h))},bindUI:function(){this.get(a).one("button."+N).on(s,this._onCollapseClick,this),this.get(a).one("input[type=checkbox]."+F).on(s,this._onPauseClick,this),this.get(a).one("button."+T).on(s,this._onClearClick,this),this.after(this._evtCat+"stringsChange",this._afterStringsChange),this.after(this._evtCat+"pausedChange",this._afterPausedChange),this.after(this._evtCat+"consoleLimitChange",this._afterConsoleLimitChange),this.after(this._evtCat+"collapsedChange",this._afterCollapsedChange)},_initHead:function(){var e=this.get(a),t=Y(et.CHROME_CLASSES,{str_collapse:this.get("strings.collapse"),str_title:this.get("strings.title")});this._head=K(Z(et.HEADER_TEMPLATE,t)),e.insertBefore(this._head,e.get("firstChild"))},_initBody:function(){this._body=K(Z(et.BODY_TEMPLATE,et.CHROME_CLASSES)),this.get(a).appendChild(this._body)},_initFoot:function(){var t=Y(et.CHROME_CLASSES,{id_guid:e.guid(),str_pause:this.get("strings.pause"),str_clear:this.get("strings.clear")});this._foot=K(Z(et.FOOTER_TEMPLATE,t)),this.get(a).appendChild(this._foot)},_isInLogLevel:function(e){var t=e.cat,n=this.get("logLevel");if(n!==p){t=t||p,G(t)&&(t=t.toLowerCase());if(t===w&&n===c||t===p&&n!==p)return!1}return!0},_normalizeMessage:function(e){var t=e.msg,n=e.cat,r=e.src,i={time:new Date,message:t,category:n||this.get("defaultCategory"),sourceAndDetail:r||this.get("defaultSource"),source:null,localTime:null,elapsedTime:null,totalTime:null};return i.source=q.test(i.sourceAndDetail)?RegExp.$1:i.sourceAndDetail,i.localTime=i.time.toLocaleTimeString?i.time.toLocaleTimeString():i.time+"",i.elapsedTime=i.time-this.get(d),i.totalTime=i.time-this.get(y),this._set(d,i.time),i},_schedulePrint:function(){!this._printLoop&&!this.get(m)&&this.get("rendered")&&(this._printLoop=e.later(this.get("printTimeout"),this,this.printBuffer,this.get("printLimit"),!0))},_createEntryHTML:function(e){return e=Y(this._htmlEscapeMessage(e),et.ENTRY_CLASSES,{cat_class:this.getClassName(l,e.category),src_class:this.getClassName(l,e.source)}),this.get("entryTemplate").replace(/\{(\w+)\}/g,function(t,n){return n in e?e[n]:""})},scrollToLatest:function(){var e=this.get("newestOnTop")?0:this._body.get("scrollHeight");this._body.set("scrollTop",e)},_htmlEscapeMessage:function(e){return e.message=this._encodeHTML(e.message),e.source=this._encodeHTML(e.source),e.sourceAndDetail=this._encodeHTML(e.sourceAndDetail),e.category=this._encodeHTML(e.category),e},_trimOldEntries:function(){e.config.debug=!1;var t=this._body,n=this.get("consoleLimit"),r=e.config.debug,i,s,o,u;if(t){i=t.all(E+_),u=i.size()-n;if(u>0){this.get("newestOnTop")?(o=n,u=i.size()):o=0,this._body.setStyle("display","none");for(;o<u;++o)s=i.item(o),s&&s.remove();this._body.setStyle("display","")}}e.config.debug=r},_encodeHTML:function(e){return G(e)?e.replace(R,W).replace(z,V).replace(U,X):e},_cancelPrintLoop:function(){this._printLoop&&(this._printLoop.cancel(),this._printLoop=null)},_validateStyle:function(e){return e==="inline"||e==="block"||e==="separate"},_onPauseClick:function(e){this.set(m,e.target.get(r))},_onClearClick:function(e){this.clearConsole()},_onCollapseClick:function(e){this.set(o,!this.get(o))},_validateLogSource:function(t){return t&&e.Lang.isFunction(t.on)},_setLogLevel:function(e){return G(e)&&(e=e.toLowerCase()),e===w||e===c?e:p},_getUseBrowserConsole:function(){var e=this.get("logSource");return e instanceof YUI?e.config.useBrowserConsole:null},_setUseBrowserConsole:function(t){var n=this.get("logSource");return n instanceof YUI?(t=!!t,n.config.useBrowserConsole=t,t):e.Attribute.INVALID_VALUE},_uiSetHeight:function(e){et.superclass._uiSetHeight.apply(this,arguments);if(this._head&&this._foot){var t=this.get("boundingBox").get("offsetHeight")-this._head.get("offsetHeight")-this._foot.get("offsetHeight");this._body.setStyle(h,t+"px")}},_uiSizeCB:function(){},_afterStringsChange:function(e){var t=e.subAttrName?e.subAttrName.split(E)[1]:null,n=this.get(a),r=e.prevVal,s=e.newVal;(!t||t===b)&&r.title!==s.title&&n.all(E+M).setHTML(s.title),(!t||t===v)&&r.pause!==s.pause&&n.all(E+I).setHTML(s.pause),(!t||t===i)&&r.clear!==s.clear&&n.all(E+T).set("value",s.clear)},_afterPausedChange:function(t){var n=t.newVal;t.src!==e.Widget.SRC_UI&&this._uiUpdatePaused(n),n?this._printLoop&&this._cancelPrintLoop():this._schedulePrint()},_uiUpdatePaused:function(e){var t=this._foot.all("input[type=checkbox]."+F);t&&t.set(r,e)},_afterConsoleLimitChange:function(){this._trimOldEntries()},_afterCollapsedChange:function(e){this._uiUpdateCollapsed(e.newVal)},_uiUpdateCollapsed:function(e){var t=this.get("boundingBox"),n=t.all("button."+N),r=e?"addClass":"removeClass",i=this.get("strings."+(e?"expand":"collapse"));t[r](C),n&&n.setHTML(i),this._uiSetHeight(e?this._head.get("offsetHeight"):this.get(h))},_afterVisibleChange:function(e){et.superclass._afterVisibleChange.apply(this,arguments),this._uiUpdateFromHideShow(e.newVal)},_uiUpdateFromHideShow:function(e){e&&this._uiSetHeight(this.get(h))},_onLogEvent:function(t){if(!this.get(f)&&this._isInLogLevel(t)){var n=e.config.debug;e.config.debug=!1,this.fire(l,{message:this._normalizeMessage(t)}),e.config.debug=n}},_defResetFn:function(){this.clearConsole(),this.set(y,new Date),this.set(f,!1),this.set(m,!1)},_defEntryFn:function(e){e.message&&(this.buffer.push(e.message),this._schedulePrint())}},{NAME:u,LOG_LEVEL_INFO:p,LOG_LEVEL_WARN:w,LOG_LEVEL_ERROR:c,ENTRY_CLASSES:{entry_class:_,entry_meta_class:H,entry_cat_class:D,entry_src_class:B,entry_time_class:j,entry_content_class:P},CHROME_CLASSES:{console_hd_class:L,console_bd_class:A,console_ft_class:O,console_controls_class:k,console_checkbox_class:x,console_pause_class:F,console_pause_label_class:I,console_button_class:S,console_clear_class:T,console_collapse_class:N,console_title_class:M},HEADER_TEMPLATE:'<div class="{console_hd_class}"><h4 class="{console_title_class}">{str_title}</h4><button type="button" class="{console_button_class} {console_collapse_class}">{str_collapse}</button></div>',BODY_TEMPLATE:'<div class="{console_bd_class}"></div>',FOOTER_TEMPLATE:'<div class="{console_ft_class}"><div class="{console_controls_class}"><label class="{console_pause_label_class}"><input type="checkbox" class="{console_checkbox_class} {console_pause_class}" value="1" id="{id_guid}"> {str_pause}</label><button type="button" class="{console_button_class} {console_clear_class}">{str_clear}</button></div></div>',ENTRY_TEMPLATE:$,ATTRS:{logEvent:{value:"yui:log",writeOnce:!0,validator:G},logSource:{value:e,writeOnce:!0,validator:function(e){return this._validateLogSource(e)}},strings:{valueFn:function(){return e.Intl.get("console")}},paused:{value:!1,validator:J.isBoolean},defaultCategory:{value:p,validator:G},defaultSource:{value:"global",validator:G},entryTemplate:{value:$,validator:G},logLevel:{value:e.config.logLevel||p,setter:function(e){return this._setLogLevel(e)}},printTimeout:{value:100,validator:Q},printLimit:{value:50,validator:Q},consoleLimit:{value:300,validator:Q},newestOnTop:{value:!0},scrollIntoView:{value:!0},startTime:{value:new Date},lastTime:{value:new Date,readOnly:!0},collapsed:{value:!1},height:{value:"300px"},width:{value:"300px"},useBrowserConsole:{lazyAdd:!1,value:!1,getter:function(){return this._getUseBrowserConsole()},setter:function(e){return this._setUseBrowserConsole(e)}},style:{value:"separate",writeOnce:!0,validator:function(e){return this._validateStyle(e)}}}})},"3.7.3",{requires:["yui-log","widget"],skinnable:!0,lang:["en","es","ja"]});
diff --git a/js/yui3/console/lang/console.js b/js/yui3/console/lang/console.js
new file mode 100644
index 000000000..b7c2f5caa
--- /dev/null
+++ b/js/yui3/console/lang/console.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/console",function(e){e.Intl.add("console","",{title:"Log Console",pause:"Pause",clear:"Clear",collapse:"Collapse",expand:"Expand"})},"3.7.3");
diff --git a/js/yui3/console/lang/console_en.js b/js/yui3/console/lang/console_en.js
new file mode 100644
index 000000000..956d228d9
--- /dev/null
+++ b/js/yui3/console/lang/console_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/console_en",function(e){e.Intl.add("console","en",{title:"Log Console",pause:"Pause",clear:"Clear",collapse:"Collapse",expand:"Expand"})},"3.7.3");
diff --git a/js/yui3/console/lang/console_es.js b/js/yui3/console/lang/console_es.js
new file mode 100644
index 000000000..460f3a172
--- /dev/null
+++ b/js/yui3/console/lang/console_es.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/console_es",function(e){e.Intl.add("console","es",{title:"Consola de informacion",pause:"Pausa",clear:"Borrar",collapse:"Colapsar",expand:"Expandir"})},"3.7.3");
diff --git a/js/yui3/console/lang/console_ja.js b/js/yui3/console/lang/console_ja.js
new file mode 100644
index 000000000..c68336196
--- /dev/null
+++ b/js/yui3/console/lang/console_ja.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/console_ja",function(e){e.Intl.add("console","ja",{title:"\u30ed\u30b0\u30b3\u30f3\u30bd\u30fc\u30eb",pause:"\u4e00\u6642\u505c\u6b62",clear:"\u30af\u30ea\u30a2",collapse:"\u9589\u3058\u308b",expand:"\u958b\u304f"})},"3.7.3");
diff --git a/js/yui3/cookie/cookie-min.js b/js/yui3/cookie/cookie-min.js
new file mode 100644
index 000000000..8ef3cad12
--- /dev/null
+++ b/js/yui3/cookie/cookie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("cookie",function(e,t){function h(e){throw new TypeError(e)}function p(e){(!s(e)||e==="")&&h("Cookie name must be a non-empty string.")}function d(e){(!s(e)||e==="")&&h("Subcookie name must be a non-empty string.")}var n=e.Lang,r=e.Object,i=null,s=n.isString,o=n.isObject,u=n.isUndefined,a=n.isFunction,f=encodeURIComponent,l=decodeURIComponent,c=e.config.doc;e.Cookie={_createCookieString:function(e,t,n,r){r=r||{};var i=f(e)+"="+(n?f(t):t),u=r.expires,a=r.path,l=r.domain;return o(r)&&(u instanceof Date&&(i+="; expires="+u.toUTCString()),s(a)&&a!==""&&(i+="; path="+a),s(l)&&l!==""&&(i+="; domain="+l),r.secure===!0&&(i+="; secure")),i},_createCookieHashString:function(e){o(e)||h("Cookie._createCookieHashString(): Argument must be an object.");var t=[];return r.each(e,function(e,n){!a(e)&&!u(e)&&t.push(f(n)+"="+f(String(e)))}),t.join("&")},_parseCookieHash:function(e){var t=e.split("&"),n=i,r={};if(e.length)for(var s=0,o=t.length;s<o;s++)n=t[s].split("="),r[l(n[0])]=l(n[1]);return r},_parseCookieString:function(e,t){var n={};if(s(e)&&e.length>0){var r=t===!1?function(e){return e}:l,o=e.split(/;\s/g),u=i,a=i,f=i;for(var c=0,h=o.length;c<h;c++){f=o[c].match(/([^=]+)=/i);if(f instanceof Array)try{u=l(f[1]),a=r(o[c].substring(f[1].length+1))}catch(p){}else u=l(o[c]),a="";n[u]=a}}return n},_setDoc:function(e){c=e},exists:function(e){p(e);var t=this._parseCookieString(c.cookie,!0);return t.hasOwnProperty(e)},get:function(e,t){p(e);var n,r,s;return a(t)?(s=t,t={}):o(t)?s=t.converter:t={},n=this._parseCookieString(c.cookie,!t.raw),r=n[e],u(r)?i:a(s)?s(r):r},getSub:function(e,t,n){var r=this.getSubs(e);return r!==i?(d(t),u(r[t])?i:a(n)?n(r[t]):r[t]):i},getSubs:function(e){p(e);var t=this._parseCookieString(c.cookie,!1);return s(t[e])?this._parseCookieHash(t[e]):i},remove:function(t,n){return p(t),n=e.merge(n||{},{expires:new Date(0)}),this.set(t,"",n)},removeSub:function(e,t,n){p(e),d(t),n=n||{};var r=this.getSubs(e);if(o(r)&&r.hasOwnProperty(t)){delete r[t];if(!n.removeIfEmpty)return this.setSubs(e,r,n);for(var i in r)if(r.hasOwnProperty(i)&&!a(r[i])&&!u(r[i]))return this.setSubs(e,r,n);return this.remove(e,n)}return""},set:function(e,t,n){p(e),u(t)&&h("Cookie.set(): Value cannot be undefined."),n=n||{};var r=this._createCookieString(e,t,!n.raw,n);return c.cookie=r,r},setSub:function(e,t,n,r){p(e),d(t),u(n)&&h("Cookie.setSub(): Subcookie value cannot be undefined.");var i=this.getSubs(e);return o(i)||(i={}),i[t]=n,this.setSubs(e,i,r)},setSubs:function(e,t,n){p(e),o(t)||h("Cookie.setSubs(): Cookie value must be an object.");var r=this._createCookieString(e,this._createCookieHashString(t),!1,n);return c.cookie=r,r}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/createlink-base/createlink-base-min.js b/js/yui3/createlink-base/createlink-base-min.js
new file mode 100644
index 000000000..d8281e534
--- /dev/null
+++ b/js/yui3/createlink-base/createlink-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("createlink-base",function(e,t){var n={};n.STRINGS={PROMPT:"Please enter the URL for the link to point to:",DEFAULT:"http://"},e.namespace("Plugin"),e.Plugin.CreateLinkBase=n,e.mix(e.Plugin.ExecCommand.COMMANDS,{createlink:function(t){var r=this.get("host").getInstance(),i,s,o,u,a=prompt(n.STRINGS.PROMPT,n.STRINGS.DEFAULT);return a&&(u=r.config.doc.createElement("div"),a=a.replace(/"/g,"").replace(/'/g,""),a=r.config.doc.createTextNode(a),u.appendChild(a),a=u.innerHTML,this.get("host")._execCommand(t,a),o=new r.EditorSelection,i=o.getSelected(),!o.isCollapsed&&i.size()?(s=i.item(0).one("a"),s&&i.item(0).replace(s),e.UA.gecko&&s.get("parentNode").test("span")&&s.get("parentNode").one("br.yui-cursor")&&s.get("parentNode").insert(s,"before")):this.get("host").execCommand("inserthtml",'<a href="'+a+'">'+a+"</a>")),s}})},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/cssbase-context/base-context-min.css b/js/yui3/cssbase-context/base-context-min.css
new file mode 100644
index 000000000..c9ef7b466
--- /dev/null
+++ b/js/yui3/cssbase-context/base-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssbase h1{font-size:138.5%}.yui3-cssbase h2{font-size:123.1%}.yui3-cssbase h3{font-size:108%}.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3{margin:1em 0}.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3,.yui3-cssbase h4,.yui3-cssbase h5,.yui3-cssbase h6,.yui3-cssbase strong{font-weight:bold}.yui3-cssbase abbr,.yui3-cssbase acronym{border-bottom:1px dotted #000;cursor:help}.yui3-cssbase em{font-style:italic}.yui3-cssbase blockquote,.yui3-cssbase ul,.yui3-cssbase ol,.yui3-cssbase dl{margin:1em}.yui3-cssbase ol,.yui3-cssbase ul,.yui3-cssbase dl{margin-left:2em}.yui3-cssbase ol{list-style:decimal outside}.yui3-cssbase ul{list-style:disc outside}.yui3-cssbase dl dd{margin-left:1em}.yui3-cssbase th,.yui3-cssbase td{border:1px solid #000;padding:.5em}.yui3-cssbase th{font-weight:bold;text-align:center}.yui3-cssbase caption{margin-bottom:.5em;text-align:center}.yui3-cssbase p,.yui3-cssbase fieldset,.yui3-cssbase table,.yui3-cssbase pre{margin-bottom:1em}.yui3-cssbase input[type=text],.yui3-cssbase input[type=password],.yui3-cssbase textarea{width:12.25em;*width:11.9em}#yui3-css-stamp.cssbase-context{display:none} \ No newline at end of file
diff --git a/js/yui3/cssbase-context/base-context.css b/js/yui3/cssbase-context/base-context.css
new file mode 100644
index 000000000..527960202
--- /dev/null
+++ b/js/yui3/cssbase-context/base-context.css
@@ -0,0 +1,81 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* base.css, part of YUI's CSS Foundation */
+.yui3-cssbase h1 {
+ /*18px via YUI Fonts CSS foundation*/
+ font-size:138.5%;
+}
+.yui3-cssbase h2 {
+ /*16px via YUI Fonts CSS foundation*/
+ font-size:123.1%;
+}
+.yui3-cssbase h3 {
+ /*14px via YUI Fonts CSS foundation*/
+ font-size:108%;
+}
+.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3 {
+ /* top & bottom margin based on font size */
+ margin:1em 0;
+}
+.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3,.yui3-cssbase h4,.yui3-cssbase h5,.yui3-cssbase h6,.yui3-cssbase strong {
+ /*bringing boldness back to headers and the strong element*/
+ font-weight:bold;
+}
+.yui3-cssbase abbr,.yui3-cssbase acronym {
+ /*indicating to users that more info is available */
+ border-bottom:1px dotted #000;
+ cursor:help;
+}
+.yui3-cssbase em {
+ /*bringing italics back to the em element*/
+ font-style:italic;
+}
+.yui3-cssbase blockquote,.yui3-cssbase ul,.yui3-cssbase ol,.yui3-cssbase dl {
+ /*giving blockquotes and lists room to breath*/
+ margin:1em;
+}
+.yui3-cssbase ol,.yui3-cssbase ul,.yui3-cssbase dl {
+ /*bringing lists on to the page with breathing room */
+ margin-left:2em;
+}
+.yui3-cssbase ol {
+ /*giving OL's LIs generated numbers*/
+ list-style: decimal outside;
+}
+.yui3-cssbase ul {
+ /*giving UL's LIs generated disc markers*/
+ list-style: disc outside;
+}
+.yui3-cssbase dl dd {
+ /*providing spacing for definition terms*/
+ margin-left:1em;
+}
+.yui3-cssbase th,.yui3-cssbase td {
+ /*borders and padding to make the table readable*/
+ border:1px solid #000;
+ padding:.5em;
+}
+.yui3-cssbase th {
+ /*distinguishing table headers from data cells*/
+ font-weight:bold;
+ text-align:center;
+}
+.yui3-cssbase caption {
+ /*coordinated margin to match cell's padding*/
+ margin-bottom:.5em;
+ /*centered so it doesn't blend in to other content*/
+ text-align:center;
+}
+.yui3-cssbase p,.yui3-cssbase fieldset,.yui3-cssbase table,.yui3-cssbase pre {
+ /*so things don't run into each other*/
+ margin-bottom:1em;
+}
+/* setting a consistent width, 160px;
+ control of type=file still not possible */
+.yui3-cssbase input[type=text],.yui3-cssbase input[type=password],.yui3-cssbase textarea{width:12.25em;*width:11.9em;}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssbase-context { display: none; }
diff --git a/js/yui3/cssbase-context/cssbase-context-min.css b/js/yui3/cssbase-context/cssbase-context-min.css
new file mode 100644
index 000000000..0486ee618
--- /dev/null
+++ b/js/yui3/cssbase-context/cssbase-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssbase h1{font-size:138.5%}.yui3-cssbase h2{font-size:123.1%}.yui3-cssbase h3{font-size:108%}.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3{margin:1em 0}.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3,.yui3-cssbase h4,.yui3-cssbase h5,.yui3-cssbase h6,.yui3-cssbase strong{font-weight:bold}.yui3-cssbase abbr,.yui3-cssbase acronym{border-bottom:1px dotted #000;cursor:help}.yui3-cssbase em{font-style:italic}.yui3-cssbase blockquote,.yui3-cssbase ul,.yui3-cssbase ol,.yui3-cssbase dl{margin:1em}.yui3-cssbase ol,.yui3-cssbase ul,.yui3-cssbase dl{margin-left:2em}.yui3-cssbase ol{list-style:decimal outside}.yui3-cssbase ul{list-style:disc outside}.yui3-cssbase dl dd{margin-left:1em}.yui3-cssbase th,.yui3-cssbase td{border:1px solid #000;padding:.5em}.yui3-cssbase th{font-weight:bold;text-align:center}.yui3-cssbase caption{margin-bottom:.5em;text-align:center}.yui3-cssbase p,.yui3-cssbase fieldset,.yui3-cssbase table,.yui3-cssbase pre{margin-bottom:1em}.yui3-cssbase input[type=text],.yui3-cssbase input[type=password],.yui3-cssbase textarea{width:12.25em;*width:11.9em}#yui3-css-stamp.cssbase-context{display:none}
diff --git a/js/yui3/cssbase-context/cssbase-context.css b/js/yui3/cssbase-context/cssbase-context.css
new file mode 100644
index 000000000..1d123b0d3
--- /dev/null
+++ b/js/yui3/cssbase-context/cssbase-context.css
@@ -0,0 +1,82 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* base.css, part of YUI's CSS Foundation */
+.yui3-cssbase h1 {
+ /*18px via YUI Fonts CSS foundation*/
+ font-size:138.5%;
+}
+.yui3-cssbase h2 {
+ /*16px via YUI Fonts CSS foundation*/
+ font-size:123.1%;
+}
+.yui3-cssbase h3 {
+ /*14px via YUI Fonts CSS foundation*/
+ font-size:108%;
+}
+.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3 {
+ /* top & bottom margin based on font size */
+ margin:1em 0;
+}
+.yui3-cssbase h1,.yui3-cssbase h2,.yui3-cssbase h3,.yui3-cssbase h4,.yui3-cssbase h5,.yui3-cssbase h6,.yui3-cssbase strong {
+ /*bringing boldness back to headers and the strong element*/
+ font-weight:bold;
+}
+.yui3-cssbase abbr,.yui3-cssbase acronym {
+ /*indicating to users that more info is available */
+ border-bottom:1px dotted #000;
+ cursor:help;
+}
+.yui3-cssbase em {
+ /*bringing italics back to the em element*/
+ font-style:italic;
+}
+.yui3-cssbase blockquote,.yui3-cssbase ul,.yui3-cssbase ol,.yui3-cssbase dl {
+ /*giving blockquotes and lists room to breath*/
+ margin:1em;
+}
+.yui3-cssbase ol,.yui3-cssbase ul,.yui3-cssbase dl {
+ /*bringing lists on to the page with breathing room */
+ margin-left:2em;
+}
+.yui3-cssbase ol {
+ /*giving OL's LIs generated numbers*/
+ list-style: decimal outside;
+}
+.yui3-cssbase ul {
+ /*giving UL's LIs generated disc markers*/
+ list-style: disc outside;
+}
+.yui3-cssbase dl dd {
+ /*providing spacing for definition terms*/
+ margin-left:1em;
+}
+.yui3-cssbase th,.yui3-cssbase td {
+ /*borders and padding to make the table readable*/
+ border:1px solid #000;
+ padding:.5em;
+}
+.yui3-cssbase th {
+ /*distinguishing table headers from data cells*/
+ font-weight:bold;
+ text-align:center;
+}
+.yui3-cssbase caption {
+ /*coordinated margin to match cell's padding*/
+ margin-bottom:.5em;
+ /*centered so it doesn't blend in to other content*/
+ text-align:center;
+}
+.yui3-cssbase p,.yui3-cssbase fieldset,.yui3-cssbase table,.yui3-cssbase pre {
+ /*so things don't run into each other*/
+ margin-bottom:1em;
+}
+/* setting a consistent width, 160px;
+ control of type=file still not possible */
+.yui3-cssbase input[type=text],.yui3-cssbase input[type=password],.yui3-cssbase textarea{width:12.25em;*width:11.9em;}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssbase-context { display: none; }
diff --git a/js/yui3/cssbase/base-min.css b/js/yui3/cssbase/base-min.css
new file mode 100644
index 000000000..61d1690b8
--- /dev/null
+++ b/js/yui3/cssbase/base-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+h1{font-size:138.5%}h2{font-size:123.1%}h3{font-size:108%}h1,h2,h3{margin:1em 0}h1,h2,h3,h4,h5,h6,strong{font-weight:bold}abbr,acronym{border-bottom:1px dotted #000;cursor:help}em{font-style:italic}blockquote,ul,ol,dl{margin:1em}ol,ul,dl{margin-left:2em}ol{list-style:decimal outside}ul{list-style:disc outside}dl dd{margin-left:1em}th,td{border:1px solid #000;padding:.5em}th{font-weight:bold;text-align:center}caption{margin-bottom:.5em;text-align:center}p,fieldset,table,pre{margin-bottom:1em}input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em}#yui3-css-stamp.cssbase{display:none} \ No newline at end of file
diff --git a/js/yui3/cssbase/base.css b/js/yui3/cssbase/base.css
new file mode 100644
index 000000000..cde32ee40
--- /dev/null
+++ b/js/yui3/cssbase/base.css
@@ -0,0 +1,81 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* base.css, part of YUI's CSS Foundation */
+h1 {
+ /*18px via YUI Fonts CSS foundation*/
+ font-size:138.5%;
+}
+h2 {
+ /*16px via YUI Fonts CSS foundation*/
+ font-size:123.1%;
+}
+h3 {
+ /*14px via YUI Fonts CSS foundation*/
+ font-size:108%;
+}
+h1,h2,h3 {
+ /* top & bottom margin based on font size */
+ margin:1em 0;
+}
+h1,h2,h3,h4,h5,h6,strong {
+ /*bringing boldness back to headers and the strong element*/
+ font-weight:bold;
+}
+abbr,acronym {
+ /*indicating to users that more info is available */
+ border-bottom:1px dotted #000;
+ cursor:help;
+}
+em {
+ /*bringing italics back to the em element*/
+ font-style:italic;
+}
+blockquote,ul,ol,dl {
+ /*giving blockquotes and lists room to breath*/
+ margin:1em;
+}
+ol,ul,dl {
+ /*bringing lists on to the page with breathing room */
+ margin-left:2em;
+}
+ol {
+ /*giving OL's LIs generated numbers*/
+ list-style: decimal outside;
+}
+ul {
+ /*giving UL's LIs generated disc markers*/
+ list-style: disc outside;
+}
+dl dd {
+ /*providing spacing for definition terms*/
+ margin-left:1em;
+}
+th,td {
+ /*borders and padding to make the table readable*/
+ border:1px solid #000;
+ padding:.5em;
+}
+th {
+ /*distinguishing table headers from data cells*/
+ font-weight:bold;
+ text-align:center;
+}
+caption {
+ /*coordinated margin to match cell's padding*/
+ margin-bottom:.5em;
+ /*centered so it doesn't blend in to other content*/
+ text-align:center;
+}
+p,fieldset,table,pre {
+ /*so things don't run into each other*/
+ margin-bottom:1em;
+}
+/* setting a consistent width, 160px;
+ control of type=file still not possible */
+input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em;}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssbase { display: none; }
diff --git a/js/yui3/cssbase/cssbase-min.css b/js/yui3/cssbase/cssbase-min.css
new file mode 100644
index 000000000..f7601f731
--- /dev/null
+++ b/js/yui3/cssbase/cssbase-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+h1{font-size:138.5%}h2{font-size:123.1%}h3{font-size:108%}h1,h2,h3{margin:1em 0}h1,h2,h3,h4,h5,h6,strong{font-weight:bold}abbr,acronym{border-bottom:1px dotted #000;cursor:help}em{font-style:italic}blockquote,ul,ol,dl{margin:1em}ol,ul,dl{margin-left:2em}ol{list-style:decimal outside}ul{list-style:disc outside}dl dd{margin-left:1em}th,td{border:1px solid #000;padding:.5em}th{font-weight:bold;text-align:center}caption{margin-bottom:.5em;text-align:center}p,fieldset,table,pre{margin-bottom:1em}input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em}#yui3-css-stamp.cssbase{display:none}
diff --git a/js/yui3/cssbase/cssbase.css b/js/yui3/cssbase/cssbase.css
new file mode 100644
index 000000000..89e41b191
--- /dev/null
+++ b/js/yui3/cssbase/cssbase.css
@@ -0,0 +1,82 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* base.css, part of YUI's CSS Foundation */
+h1 {
+ /*18px via YUI Fonts CSS foundation*/
+ font-size:138.5%;
+}
+h2 {
+ /*16px via YUI Fonts CSS foundation*/
+ font-size:123.1%;
+}
+h3 {
+ /*14px via YUI Fonts CSS foundation*/
+ font-size:108%;
+}
+h1,h2,h3 {
+ /* top & bottom margin based on font size */
+ margin:1em 0;
+}
+h1,h2,h3,h4,h5,h6,strong {
+ /*bringing boldness back to headers and the strong element*/
+ font-weight:bold;
+}
+abbr,acronym {
+ /*indicating to users that more info is available */
+ border-bottom:1px dotted #000;
+ cursor:help;
+}
+em {
+ /*bringing italics back to the em element*/
+ font-style:italic;
+}
+blockquote,ul,ol,dl {
+ /*giving blockquotes and lists room to breath*/
+ margin:1em;
+}
+ol,ul,dl {
+ /*bringing lists on to the page with breathing room */
+ margin-left:2em;
+}
+ol {
+ /*giving OL's LIs generated numbers*/
+ list-style: decimal outside;
+}
+ul {
+ /*giving UL's LIs generated disc markers*/
+ list-style: disc outside;
+}
+dl dd {
+ /*providing spacing for definition terms*/
+ margin-left:1em;
+}
+th,td {
+ /*borders and padding to make the table readable*/
+ border:1px solid #000;
+ padding:.5em;
+}
+th {
+ /*distinguishing table headers from data cells*/
+ font-weight:bold;
+ text-align:center;
+}
+caption {
+ /*coordinated margin to match cell's padding*/
+ margin-bottom:.5em;
+ /*centered so it doesn't blend in to other content*/
+ text-align:center;
+}
+p,fieldset,table,pre {
+ /*so things don't run into each other*/
+ margin-bottom:1em;
+}
+/* setting a consistent width, 160px;
+ control of type=file still not possible */
+input[type=text],input[type=password],textarea{width:12.25em;*width:11.9em;}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssbase { display: none; }
diff --git a/js/yui3/cssbutton/cssbutton-min.css b/js/yui3/cssbutton/cssbutton-min.css
new file mode 100644
index 000000000..85737037c
--- /dev/null
+++ b/js/yui3/cssbutton/cssbutton-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-button{display:inline-block;*display:inline;zoom:1;font-size:100%;*font-size:90%;*overflow:visible;padding:.4em 1em .45em;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;color:#444;color:rgba(0,0,0,0.80);*color:#444;border:1px solid #999;border:none rgba(0,0,0,0);background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80ffffff',endColorstr='#00ffffff',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(255,255,255,0.30)),color-stop(40%,rgba(255,255,255,0.15)),to(transparent));background-image:-webkit-linear-gradient(rgba(255,255,255,0.30),rgba(255,255,255,0.15) 40%,transparent);background-image:-moz-linear-gradient(top,rgba(255,255,255,0.30),rgba(255,255,255,0.15) 40%,transparent);background-image:-ms-linear-gradient(rgba(255,255,255,0.30),rgba(255,255,255,0.15) 40%,transparent);background-image:-o-linear-gradient(rgba(255,255,255,0.30),rgba(255,255,255,0.15) 40%,transparent);background-image:linear-gradient(rgba(255,255,255,0.30),rgba(255,255,255,0.15) 40%,transparent);text-decoration:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.30) inset,0 1px 2px rgba(0,0,0,0.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.30) inset,0 1px 2px rgba(0,0,0,0.15);box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.30) inset,0 1px 2px rgba(0,0,0,0.15);-webkit-transition:.1s linear -webkit-box-shadow;-moz-transition:.1s linear -moz-box-shadow;-ms-transition:.1s linear box-shadow;-o-transition:.1s linear box-shadow;transition:.1s linear box-shadow}a.yui3-button{color:rgba(0,0,0,0.80);color:#444;text-decoration:none}.yui3-button-hover,.yui3-button:hover{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,0.05)),to(rgba(0,0,0,0.15)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:-moz-linear-gradient(top,transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:-ms-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:-o-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15))}.yui3-button-active,.yui3-button:active{border:inset 1px solid #999;border:none rgba(0,0,0,0);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1A000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(0,0,0,0.10)),to(rgba(0,0,0,0.15)));background-image:-webkit-linear-gradient(rgba(0,0,0,0.10),rgba(0,0,0,0.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0.10),rgba(0,0,0,0.15));background-image:-ms-linear-gradient(rgba(0,0,0,0.10),rgba(0,0,0,0.15));background-image:-o-linear-gradient(rgba(0,0,0,0.10),rgba(0,0,0,0.15));background-image:linear-gradient(rgba(0,0,0,0.10),rgba(0,0,0,0.15));-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 4px rgba(0,0,0,0.30) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 4px rgba(0,0,0,0.30) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 4px rgba(0,0,0,0.30) inset}.yui3-button[disabled],.yui3-button-disabled,.yui3-button-disabled:hover,.yui3-button-disabled:active{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=55);-khtml-opacity:.55;-moz-opacity:.55;opacity:.55;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset;box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset}.yui3-button::-moz-focus-inner{padding:0;border:0}.yui3-button:-moz-focusring{outline:thin dotted}.yui3-skin-sam .yui3-button-primary,.yui3-skin-sam .yui3-button-selected{background-color:#345fcb;color:#fff;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.17) inset,0 1px 2px rgba(0,0,0,0.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.17) inset,0 1px 2px rgba(0,0,0,0.15);box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.17) inset,0 1px 2px rgba(0,0,0,0.15)}.yui3-skin-sam .yui3-button:-moz-focusring{outline-color:rgba(0,0,0,0.85)}.yui3-skin-night .yui3-button{border:0;background-color:#343536;color:#dcdcdc;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.15) inset,0 1px 2px rgba(0,0,0,0.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.15) inset,0 1px 2px rgba(0,0,0,0.15);box-shadow:0 0 0 1px rgba(0,0,0,0.25) inset,0 2px 0 rgba(255,255,255,0.15) inset,0 1px 2px rgba(0,0,0,0.15)}.yui3-skin-night .yui3-button-primary,.yui3-skin-night .yui3-button-selected{background-color:#747576;text-shadow:0 1px 2px rgba(0,0,0,0.7)}.yui3-skin-night .yui3-button:-moz-focusring{outline-color:rgba(255,255,255,0.85)}#yui3-css-stamp.cssbutton{display:none}
diff --git a/js/yui3/cssbutton/cssbutton.css b/js/yui3/cssbutton/cssbutton.css
new file mode 100644
index 000000000..cb692a9d9
--- /dev/null
+++ b/js/yui3/cssbutton/cssbutton.css
@@ -0,0 +1,149 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-button {
+ /* Structure */
+ display: inline-block;
+ *display: inline; /*IE 6/7*/
+ zoom: 1;
+ font-size: 100%;
+ *font-size: 90%; /*IE 6/7 - To reduce IE's oversized button text*/
+ *overflow: visible; /*IE 6/7 - Because of IE's overly large left/right padding on buttons */
+ padding: 0.4em 1em 0.45em;
+ line-height: normal;
+ white-space: nowrap;
+ vertical-align: baseline;
+ text-align: center;
+ cursor: pointer;
+ -webkit-user-drag: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+
+ /* Presentation */
+ color: #444; /* rgba not supported (IE 8) */
+ color: rgba(0, 0, 0, 0.80); /* rgba supported */
+ *color: #444; /* IE 6 & 7 */
+ border: 1px solid #999; /*IE 6/7/8*/
+ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
+ background-color: #E6E6E6;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80ffffff', endColorstr='#00ffffff', GradientType=0);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(255,255,255, 0.30)), color-stop(40%, rgba(255,255,255, 0.15)), to(transparent));
+ background-image: -webkit-linear-gradient(rgba(255,255,255, 0.30), rgba(255,255,255, 0.15) 40%, transparent);
+ background-image: -moz-linear-gradient(top, rgba(255,255,255, 0.30), rgba(255,255,255, 0.15) 40%, transparent);
+ background-image: -ms-linear-gradient(rgba(255,255,255, 0.30), rgba(255,255,255, 0.15) 40%, transparent);
+ background-image: -o-linear-gradient(rgba(255,255,255, 0.30), rgba(255,255,255, 0.15) 40%, transparent);
+ background-image: linear-gradient(rgba(255,255,255, 0.30), rgba(255,255,255, 0.15) 40%, transparent);
+ text-decoration: none;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 0 rgba(255,255,255, 0.30) inset, 0 1px 2px rgba(0,0,0, 0.15);
+ -moz-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 0 rgba(255,255,255, 0.30) inset, 0 1px 2px rgba(0,0,0, 0.15);
+ box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 0 rgba(255,255,255, 0.30) inset, 0 1px 2px rgba(0,0,0, 0.15);
+
+ /* Transitions */
+ -webkit-transition: 0.1s linear -webkit-box-shadow;
+ -moz-transition: 0.1s linear -moz-box-shadow;
+ -ms-transition: 0.1s linear box-shadow;
+ -o-transition: 0.1s linear box-shadow;
+ transition: 0.1s linear box-shadow;
+}
+
+a.yui3-button {
+ color: rgba(0,0,0, 0.80);
+ color: #444;
+ text-decoration:none;
+}
+
+.yui3-button-hover,
+.yui3-button:hover {
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#26000000', GradientType=0);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0, 0.05)), to(rgba(0,0,0, 0.15)));
+ background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
+ background-image: -moz-linear-gradient(top, transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
+ background-image: -ms-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
+ background-image: -o-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
+ background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
+}
+
+.yui3-button-active,
+.yui3-button:active {
+ border: inset 1px solid #999; /*IE 6/7/8*/
+ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#1A000000', endColorstr='#26000000', GradientType=0);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0,0,0, 0.10)), to(rgba(0,0,0, 0.15)));
+ background-image: -webkit-linear-gradient(rgba(0,0,0, 0.10), rgba(0,0,0, 0.15));
+ background-image: -moz-linear-gradient(top, rgba(0,0,0, 0.10), rgba(0,0,0, 0.15));
+ background-image: -ms-linear-gradient(rgba(0,0,0, 0.10), rgba(0,0,0, 0.15));
+ background-image: -o-linear-gradient(rgba(0,0,0, 0.10), rgba(0,0,0, 0.15));
+ background-image: linear-gradient(rgba(0,0,0, 0.10), rgba(0,0,0, 0.15));
+ -webkit-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 4px rgba(0,0,0, 0.30) inset;
+ -moz-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 4px rgba(0,0,0, 0.30) inset;
+ box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset, 0 2px 4px rgba(0,0,0, 0.30) inset;
+}
+
+.yui3-button[disabled],
+.yui3-button-disabled,
+.yui3-button-disabled:hover,
+.yui3-button-disabled:active {
+ cursor: default;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ filter: alpha(opacity=55);
+ -khtml-opacity: 0.55;
+ -moz-opacity: 0.55;
+ opacity: 0.55;
+ -webkit-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset;
+ -moz-box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset;
+ box-shadow: 0 0 0 1px rgba(0,0,0, 0.25) inset;
+}
+
+/* Firefox: Get rid of the inner focus border */
+.yui3-button::-moz-focus-inner{
+ padding: 0;
+ border: 0;
+}
+
+/* Firefox: Add a border around a focused button */
+.yui3-button:-moz-focusring {
+ outline: thin dotted;
+}
+
+/* Sam */
+.yui3-skin-sam .yui3-button-primary,
+.yui3-skin-sam .yui3-button-selected {
+ background-color: #345FCB;
+ color: #fff;
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.17) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.17) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.17) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+}
+.yui3-skin-sam .yui3-button:-moz-focusring {
+ outline-color: rgba(0, 0, 0, 0.85);
+}
+
+/* Night */
+.yui3-skin-night .yui3-button {
+ border: 0px;
+ background-color: #343536;
+ color: #DCDCDC;
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.15) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.15) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25) inset, 0 2px 0 rgba(255, 255, 255, 0.15) inset, 0 1px 2px rgba(0, 0, 0, 0.15);
+}
+.yui3-skin-night .yui3-button-primary,
+.yui3-skin-night .yui3-button-selected {
+ background-color: #747576;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
+}
+
+.yui3-skin-night .yui3-button:-moz-focusring {
+ outline-color: rgba(255, 255, 255, 0.85);
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssbutton { display: none; }
diff --git a/js/yui3/cssfonts-context/cssfonts-context-min.css b/js/yui3/cssfonts-context/cssfonts-context-min.css
new file mode 100644
index 000000000..836ec738a
--- /dev/null
+++ b/js/yui3/cssfonts-context/cssfonts-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssfonts body,.yui3-cssfonts{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small}.yui3-cssfonts select,.yui3-cssfonts input,.yui3-cssfonts button,.yui3-cssfonts textarea{font:99% arial,helvetica,clean,sans-serif}.yui3-cssfonts table{font-size:inherit;font:100%}.yui3-cssfonts pre,.yui3-cssfonts code,.yui3-cssfonts kbd,.yui3-cssfonts samp,.yui3-cssfonts tt{font-family:monospace;*font-size:108%;line-height:100%}#yui3-css-stamp.cssfonts-context{display:none}
diff --git a/js/yui3/cssfonts-context/cssfonts-context.css b/js/yui3/cssfonts-context/cssfonts-context.css
new file mode 100644
index 000000000..12dc270d6
--- /dev/null
+++ b/js/yui3/cssfonts-context/cssfonts-context.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/**
+ * Percents could work for IE, but for backCompat purposes, we are using keywords.
+ * x-small is for IE6/7 quirks mode.
+ */
+.yui3-cssfonts body, .yui3-cssfonts {
+ font:13px/1.231 arial,helvetica,clean,sans-serif;
+ *font-size:small; /* for IE */
+ *font:x-small; /* for IE in quirks mode */
+}
+
+/**
+ * Nudge down to get to 13px equivalent for these form elements
+ */
+.yui3-cssfonts select,
+.yui3-cssfonts input,
+.yui3-cssfonts button,
+.yui3-cssfonts textarea {
+ font:99% arial,helvetica,clean,sans-serif;
+}
+
+/**
+ * To help tables remember to inherit
+ */
+.yui3-cssfonts table {
+ font-size:inherit;
+ font:100%;
+}
+
+/**
+ * Bump up IE to get to 13px equivalent for these fixed-width elements
+ */
+.yui3-cssfonts pre,
+.yui3-cssfonts code,
+.yui3-cssfonts kbd,
+.yui3-cssfonts samp,
+.yui3-cssfonts tt {
+ font-family:monospace;
+ *font-size:108%;
+ line-height:100%;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssfonts-context { display: none; }
diff --git a/js/yui3/cssfonts-context/fonts-context-min.css b/js/yui3/cssfonts-context/fonts-context-min.css
new file mode 100644
index 000000000..20d612aa2
--- /dev/null
+++ b/js/yui3/cssfonts-context/fonts-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssfonts body,.yui3-cssfonts{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small}.yui3-cssfonts select,.yui3-cssfonts input,.yui3-cssfonts button,.yui3-cssfonts textarea{font:99% arial,helvetica,clean,sans-serif}.yui3-cssfonts table{font-size:inherit;font:100%}.yui3-cssfonts pre,.yui3-cssfonts code,.yui3-cssfonts kbd,.yui3-cssfonts samp,.yui3-cssfonts tt{font-family:monospace;*font-size:108%;line-height:100%}#yui3-css-stamp.cssfonts-context{display:none} \ No newline at end of file
diff --git a/js/yui3/cssfonts-context/fonts-context.css b/js/yui3/cssfonts-context/fonts-context.css
new file mode 100644
index 000000000..12dc270d6
--- /dev/null
+++ b/js/yui3/cssfonts-context/fonts-context.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/**
+ * Percents could work for IE, but for backCompat purposes, we are using keywords.
+ * x-small is for IE6/7 quirks mode.
+ */
+.yui3-cssfonts body, .yui3-cssfonts {
+ font:13px/1.231 arial,helvetica,clean,sans-serif;
+ *font-size:small; /* for IE */
+ *font:x-small; /* for IE in quirks mode */
+}
+
+/**
+ * Nudge down to get to 13px equivalent for these form elements
+ */
+.yui3-cssfonts select,
+.yui3-cssfonts input,
+.yui3-cssfonts button,
+.yui3-cssfonts textarea {
+ font:99% arial,helvetica,clean,sans-serif;
+}
+
+/**
+ * To help tables remember to inherit
+ */
+.yui3-cssfonts table {
+ font-size:inherit;
+ font:100%;
+}
+
+/**
+ * Bump up IE to get to 13px equivalent for these fixed-width elements
+ */
+.yui3-cssfonts pre,
+.yui3-cssfonts code,
+.yui3-cssfonts kbd,
+.yui3-cssfonts samp,
+.yui3-cssfonts tt {
+ font-family:monospace;
+ *font-size:108%;
+ line-height:100%;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssfonts-context { display: none; }
diff --git a/js/yui3/cssfonts/cssfonts-min.css b/js/yui3/cssfonts/cssfonts-min.css
new file mode 100644
index 000000000..c14568d37
--- /dev/null
+++ b/js/yui3/cssfonts/cssfonts-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif}table{font-size:inherit;font:100%}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%}#yui3-css-stamp.cssfonts{display:none}
diff --git a/js/yui3/cssfonts/cssfonts.css b/js/yui3/cssfonts/cssfonts.css
new file mode 100644
index 000000000..a25a1ec54
--- /dev/null
+++ b/js/yui3/cssfonts/cssfonts.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/**
+ * Percents could work for IE, but for backCompat purposes, we are using keywords.
+ * x-small is for IE6/7 quirks mode.
+ */
+body {
+ font:13px/1.231 arial,helvetica,clean,sans-serif;
+ *font-size:small; /* for IE */
+ *font:x-small; /* for IE in quirks mode */
+}
+
+/**
+ * Nudge down to get to 13px equivalent for these form elements
+ */
+select,
+input,
+button,
+textarea {
+ font:99% arial,helvetica,clean,sans-serif;
+}
+
+/**
+ * To help tables remember to inherit
+ */
+table {
+ font-size:inherit;
+ font:100%;
+}
+
+/**
+ * Bump up IE to get to 13px equivalent for these fixed-width elements
+ */
+pre,
+code,
+kbd,
+samp,
+tt {
+ font-family:monospace;
+ *font-size:108%;
+ line-height:100%;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssfonts { display: none; }
diff --git a/js/yui3/cssfonts/fonts-min.css b/js/yui3/cssfonts/fonts-min.css
new file mode 100644
index 000000000..9a8e5ffe5
--- /dev/null
+++ b/js/yui3/cssfonts/fonts-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif}table{font-size:inherit;font:100%}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%}#yui3-css-stamp.cssfonts{display:none} \ No newline at end of file
diff --git a/js/yui3/cssfonts/fonts.css b/js/yui3/cssfonts/fonts.css
new file mode 100644
index 000000000..a25a1ec54
--- /dev/null
+++ b/js/yui3/cssfonts/fonts.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/**
+ * Percents could work for IE, but for backCompat purposes, we are using keywords.
+ * x-small is for IE6/7 quirks mode.
+ */
+body {
+ font:13px/1.231 arial,helvetica,clean,sans-serif;
+ *font-size:small; /* for IE */
+ *font:x-small; /* for IE in quirks mode */
+}
+
+/**
+ * Nudge down to get to 13px equivalent for these form elements
+ */
+select,
+input,
+button,
+textarea {
+ font:99% arial,helvetica,clean,sans-serif;
+}
+
+/**
+ * To help tables remember to inherit
+ */
+table {
+ font-size:inherit;
+ font:100%;
+}
+
+/**
+ * Bump up IE to get to 13px equivalent for these fixed-width elements
+ */
+pre,
+code,
+kbd,
+samp,
+tt {
+ font-family:monospace;
+ *font-size:108%;
+ line-height:100%;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssfonts { display: none; }
diff --git a/js/yui3/cssgrids-base/cssgrids-base-min.css b/js/yui3/cssgrids-base/cssgrids-base-min.css
new file mode 100644
index 000000000..5bdc62e51
--- /dev/null
+++ b/js/yui3/cssgrids-base/cssgrids-base-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g{letter-spacing:-0.31em;*letter-spacing:normal;word-spacing:-0.43em}.yui3-u{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}#yui3-css-stamp.cssgrids-base{display:none}
diff --git a/js/yui3/cssgrids-base/cssgrids-base.css b/js/yui3/cssgrids-base/cssgrids-base.css
new file mode 100644
index 000000000..d0d9c93d1
--- /dev/null
+++ b/js/yui3/cssgrids-base/cssgrids-base.css
@@ -0,0 +1,22 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g {
+ letter-spacing: -0.31em; /* webkit: collapse white-space between units */
+ *letter-spacing: normal; /* reset IE < 8 */
+ word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
+}
+
+.yui3-u {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssgrids-base { display: none; }
diff --git a/js/yui3/cssgrids-context-deprecated/grids-context-min.css b/js/yui3/cssgrids-context-deprecated/grids-context-min.css
new file mode 100644
index 000000000..21fec6b0d
--- /dev/null
+++ b/js/yui3/cssgrids-context-deprecated/grids-context-min.css
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssgrids body{text-align:center;margin-left:auto;margin-right:auto}.yui3-cssgrids .yui3-d0,.yui3-cssgrids .yui3-d1,.yui3-cssgrids .yui3-d1f,.yui3-cssgrids .yui3-d2,.yui3-cssgrids .yui3-d2f,.yui3-cssgrids .yui3-d3,.yui3-cssgrids .yui3-d3f{margin:auto;text-align:left;width:57.69em;*width:56.25em}.yui3-cssgrids .yui3-t1,.yui3-cssgrids .yui3-t2,.yui3-cssgrids .yui3-t3,.yui3-cssgrids .yui3-t4,.yui3-cssgrids .yui3-t5,.yui3-cssgrids .yui3-t6{margin:auto;text-align:left;width:100%}.yui3-cssgrids .yui3-d0{margin:auto 10px;width:auto}.yui3-cssgrids .yui3-d0f{width:100%}.yui3-cssgrids .yui3-d2{width:73.076em;*width:71.25em}.yui3-cssgrids .yui3-d2f{width:950px}.yui3-cssgrids .yui3-d3{width:74.923em;*width:73.05em}.yui3-cssgrids .yui3-d3f{width:974px}.yui3-cssgrids .yui3-b{position:relative}.yui3-cssgrids .yui3-b{_position:static}.yui3-cssgrids .yui3-main .yui3-b{position:static}.yui3-cssgrids .yui3-main{width:100%}.yui3-cssgrids .yui3-t1 .yui3-main,.yui3-cssgrids .yui3-t2 .yui3-main,.yui3-cssgrids .yui3-t3 .yui3-main{float:right;margin-left:-25em}.yui3-cssgrids .yui3-t4 .yui3-main,.yui3-cssgrids .yui3-t5 .yui3-main,.yui3-cssgrids .yui3-t6 .yui3-main{float:left;margin-right:-25em}.yui3-cssgrids .yui3-t1 .yui3-b{float:left;width:12.30769em;*width:12.00em}.yui3-cssgrids .yui3-t1 .yui3-main .yui3-b{margin-left:13.30769em;*margin-left:12.975em}.yui3-cssgrids .yui3-t2 .yui3-b{float:left;width:13.84615em;*width:13.50em}.yui3-cssgrids .yui3-t2 .yui3-main .yui3-b{margin-left:14.84615em;*margin-left:14.475em}.yui3-cssgrids .yui3-t3 .yui3-b{float:left;width:23.0769em;*width:22.50em}.yui3-cssgrids .yui3-t3 .yui3-main .yui3-b{margin-left:24.0769em;*margin-left:23.475em}.yui3-cssgrids .yui3-t4 .yui3-b{float:right;width:13.8456em;*width:13.50em}.yui3-cssgrids .yui3-t4 .yui3-main .yui3-b{margin-right:14.8456em;*margin-right:14.475em}.yui3-cssgrids .yui3-t5 .yui3-b{float:right;width:18.4615em;*width:18.00em}.yui3-cssgrids .yui3-t5 .yui3-main .yui3-b{margin-right:19.4615em;*margin-right:18.975em}.yui3-cssgrids .yui3-t6 .yui3-b{float:right;width:23.0769em;*width:22.50em}.yui3-cssgrids .yui3-t6 .yui3-main .yui3-b{margin-right:24.0769em;*margin-right:23.475em}.yui3-cssgrids .yui3-main .yui3-b{float:none;width:auto}.yui3-cssgrids .yui3-gb .yui3-u,.yui3-cssgrids .yui3-g .yui3-gb .yui3-u,.yui3-cssgrids .yui3-gb .yui3-g,.yui3-cssgrids .yui3-gb .yui3-gb,.yui3-cssgrids .yui3-gb .yui3-gc,.yui3-cssgrids .yui3-gb .yui3-gd,.yui3-cssgrids .yui3-gb .yui3-ge,.yui3-cssgrids .yui3-gb .yui3-gf,.yui3-cssgrids .yui3-gc .yui3-u,.yui3-cssgrids .yui3-gc .yui3-g,.yui3-cssgrids .yui3-gd .yui3-u{float:left}.yui3-cssgrids .yui3-g .yui3-u,.yui3-cssgrids .yui3-g .yui3-g,.yui3-cssgrids .yui3-g .yui3-gb,.yui3-cssgrids .yui3-g .yui3-gc,.yui3-cssgrids .yui3-g .yui3-gd,.yui3-cssgrids .yui3-g .yui3-ge,.yui3-cssgrids .yui3-g .yui3-gf,.yui3-cssgrids .yui3-gc .yui3-u,.yui3-cssgrids .yui3-gd .yui3-g,.yui3-cssgrids .yui3-g .yui3-gc .yui3-u,.yui3-cssgrids .yui3-ge .yui3-u,.yui3-cssgrids .yui3-ge .yui3-g,.yui3-cssgrids .yui3-gf .yui3-g,.yui3-cssgrids .yui3-gf .yui3-u{float:right}.yui3-cssgrids .yui3-g div.first,.yui3-cssgrids .yui3-gb div.first,.yui3-cssgrids .yui3-gc div.first,.yui3-cssgrids .yui3-gd div.first,.yui3-cssgrids .yui3-ge div.first,.yui3-cssgrids .yui3-gf div.first,.yui3-cssgrids .yui3-g .yui3-gc div.first,.yui3-cssgrids .yui3-g .yui3-ge div.first,.yui3-cssgrids .yui3-gc div.first div.first{float:left}.yui3-cssgrids .yui3-g .yui3-u,.yui3-cssgrids .yui3-g .yui3-g,.yui3-cssgrids .yui3-g .yui3-gb,.yui3-cssgrids .yui3-g .yui3-gc,.yui3-cssgrids .yui3-g .yui3-gd,.yui3-cssgrids .yui3-g .yui3-ge,.yui3-cssgrids .yui3-g .yui3-gf{width:49.1%}.yui3-cssgrids .yui3-gb .yui3-u,.yui3-cssgrids .yui3-g .yui3-gb .yui3-u,.yui3-cssgrids .yui3-gb .yui3-g,.yui3-cssgrids .yui3-gb .yui3-gb,.yui3-cssgrids .yui3-gb .yui3-gc,.yui3-cssgrids .yui3-gb .yui3-gd,.yui3-cssgrids .yui3-gb .yui3-ge,.yui3-cssgrids .yui3-gb .yui3-gf,.yui3-cssgrids .yui3-gc .yui3-u,.yui3-cssgrids .yui3-gc .yui3-g,.yui3-cssgrids .yui3-gd .yui3-u{width:32%;margin-left:2.0%}.yui3-cssgrids .yui3-gb .yui3-u{*width:31.8%;*margin-left:1.9%}.yui3-cssgrids .yui3-gc div.first,.yui3-cssgrids .yui3-gd .yui3-u{width:66%;_width:65.7%}.yui3-cssgrids .yui3-gd div.first{width:32%;_width:31.5%}.yui3-cssgrids .yui3-ge div.first,.yui3-cssgrids .yui3-gf .yui3-u{width:74.2%;_width:74%}.yui3-cssgrids .yui3-ge .yui3-u,.yui3-cssgrids .yui3-gf div.first{width:24%;_width:23.8%}.yui3-cssgrids .yui3-g .yui3-gb div.first,.yui3-cssgrids .yui3-gb div.first,.yui3-cssgrids .yui3-gc div.first,.yui3-cssgrids .yui3-gd div.first{margin-left:0}.yui3-cssgrids .yui3-g .yui3-g .yui3-u,.yui3-cssgrids .yui3-gb .yui3-g .yui3-u,.yui3-cssgrids .yui3-gc .yui3-g .yui3-u,.yui3-cssgrids .yui3-gd .yui3-g .yui3-u,.yui3-cssgrids .yui3-ge .yui3-g .yui3-u,.yui3-cssgrids .yui3-gf .yui3-g .yui3-u{width:49%;*width:48.1%;*margin-left:0}.yui3-cssgrids .yui3-g .yui3-gb div.first,.yui3-cssgrids .yui3-gb .yui3-gb div.first{*margin-right:0;*width:32%;_width:31.7%}.yui3-cssgrids .yui3-g .yui3-gc div.first,.yui3-cssgrids .yui3-gd .yui3-g{width:66%}.yui3-cssgrids .yui3-gb .yui3-g div.first{*margin-right:4%;_margin-right:1.3%}.yui3-cssgrids .yui3-gb .yui3-gc div.first,.yui3-cssgrids .yui3-gb .yui3-gd div.first{*margin-right:0}.yui3-cssgrids .yui3-gb .yui3-gb .yui3-u,.yui3-cssgrids .yui3-gb .yui3-gc .yui3-u{*margin-left:1.8%;_margin-left:4%}.yui3-cssgrids .yui3-g .yui3-gb .yui3-u{_margin-left:1.0%}.yui3-cssgrids .yui3-gb .yui3-gd .yui3-u{*width:66%;_width:61.2%}.yui3-cssgrids .yui3-gb .yui3-gd div.first{*width:31%;_width:29.5%}.yui3-cssgrids .yui3-g .yui3-gc .yui3-u,.yui3-cssgrids .yui3-gb .yui3-gc .yui3-u{width:32%;_float:right;margin-right:0;_margin-left:0}.yui3-cssgrids .yui3-gb .yui3-gc div.first{width:66%;*float:left;*margin-left:0}.yui3-cssgrids .yui3-gb .yui3-ge .yui3-u,.yui3-cssgrids .yui3-gb .yui3-gf .yui3-u{margin:0}.yui3-cssgrids .yui3-gb .yui3-gb .yui3-u{_margin-left:.7%}.yui3-cssgrids .yui3-gb .yui3-g div.first,.yui3-cssgrids .yui3-gb .yui3-gb div.first{*margin-left:0}
+.yui3-cssgrids .yui3-gc .yui3-g .yui3-u,.yui3-cssgrids .yui3-gd .yui3-g .yui3-u{*width:48.1%;*margin-left:0}.yui3-cssgrids .yui3-gb .yui3-gd div.first{width:32%}.yui3-cssgrids .yui3-g .yui3-gd div.first{_width:29.9%}.yui3-cssgrids .yui3-ge .yui3-g{width:24%}.yui3-cssgrids .yui3-gf .yui3-g{width:74.2%}.yui3-cssgrids .yui3-gb .yui3-ge div.yui3-u,.yui3-cssgrids .yui3-gb .yui3-gf div.yui3-u{float:right}.yui3-cssgrids .yui3-gb .yui3-ge div.first,.yui3-cssgrids .yui3-gb .yui3-gf div.first{float:left}.yui3-cssgrids .yui3-gb .yui3-ge .yui3-u,.yui3-cssgrids .yui3-gb .yui3-gf div.first{*width:24%;_width:20%}.yui3-cssgrids .yui3-gc .yui3-gf .yui3-u{width:74%;_width:73%}.yui3-cssgrids .yui3-gc .yui3-gf div.first{width:24%}.yui3-cssgrids .yui3-gb .yui3-ge div.first,.yui3-cssgrids .yui3-gb .yui3-gf .yui3-u{*width:73.5%;_width:65.5%}.yui3-cssgrids .yui3-ge div.first .yui3-gd .yui3-u{width:65%}.yui3-cssgrids .yui3-ge div.first .yui3-gd div.first{width:32%}.yui3-cssgrids #bd:after,.yui3-cssgrids .yui3-g:after,.yui3-cssgrids .yui3-gb:after,.yui3-cssgrids .yui3-gc:after,.yui3-cssgrids .yui3-gd:after,.yui3-cssgrids .yui3-ge:after,.yui3-cssgrids .yui3-gf:after,.yui3-cssgrids .yui3-t1:after,.yui3-cssgrids .yui3-t2:after,.yui3-cssgrids .yui3-t3:after,.yui3-cssgrids .yui3-t4:after,.yui3-cssgrids .yui3-t5:after,.yui3-cssgrids .yui3-t6:after{content:".";display:block;height:0;clear:both;visibility:hidden}.yui3-cssgrids #bd,.yui3-cssgrids .yui3-g,.yui3-cssgrids .yui3-gb,.yui3-cssgrids .yui3-gc,.yui3-cssgrids .yui3-gd,.yui3-cssgrids .yui3-ge,.yui3-cssgrids .yui3-gf,.yui3-cssgrids .yui3-t1,.yui3-cssgrids .yui3-t2,.yui3-cssgrids .yui3-t3,.yui3-cssgrids .yui3-t4,.yui3-cssgrids .yui3-t5,.yui3-cssgrids .yui3-t6{zoom:1} \ No newline at end of file
diff --git a/js/yui3/cssgrids-context-deprecated/grids-context.css b/js/yui3/cssgrids-context-deprecated/grids-context.css
new file mode 100644
index 000000000..c0407c03a
--- /dev/null
+++ b/js/yui3/cssgrids-context-deprecated/grids-context.css
@@ -0,0 +1,490 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/*
+*
+* The YUI CSS Foundation uses the *property and _property CSS filter
+* techniques to shield a value from A-grade browsers [1] other than
+* IE6 & IE7 (*property) and IE6 (_property)
+*
+/
+Section: General Rules
+*/
+.yui3-cssgrids body {
+ /* center the page */
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+}
+/*
+Section: Page Width Rules (#doc, #doc2, #doc3, #doc4)
+*/
+/*
+Subsection: General
+*/
+.yui3-cssgrids .yui3-d0, /* 100% */
+.yui3-cssgrids .yui3-d1, /* 750px */
+.yui3-cssgrids .yui3-d1f, /* 750px fixed */
+.yui3-cssgrids .yui3-d2, /* 950px */
+.yui3-cssgrids .yui3-d2f, /* 950px fixed */
+.yui3-cssgrids .yui3-d3, /* 974px */
+.yui3-cssgrids .yui3-d3f { /* 974px fixed */
+ margin: auto;
+ text-align: left;
+ width: 57.69em;
+ *width: 56.25em; /* doc1*/
+}
+
+.yui3-cssgrids .yui3-t1,
+.yui3-cssgrids .yui3-t2,
+.yui3-cssgrids .yui3-t3,
+.yui3-cssgrids .yui3-t4,
+.yui3-cssgrids .yui3-t5,
+.yui3-cssgrids .yui3-t6 {
+ margin: auto;
+ text-align: left;
+ width: 100%;
+}
+
+/*
+Subsection: 100% (doc)
+*/
+.yui3-cssgrids .yui3-d0 {
+ /* Left and Right margins are not a structural part of Grids. Without them Grids
+ works fine, but content bleeds to the very edge of the document, which often
+ impairs readability and usability. They are
+ provided because they prevent the content from "bleeding" into the browser's chrome.*/
+ margin: auto 10px;
+ width: auto;
+}
+.yui3-cssgrids .yui3-d0f {
+ width: 100%;
+}
+
+/*
+Subsection: 950 Centered (doc2)
+*/
+.yui3-cssgrids .yui3-d2 {
+ width: 73.076em;
+ *width: 71.25em;
+}
+.yui3-cssgrids .yui3-d2f {
+ width: 950px;
+}
+/*
+Subsection: 974 Centered (doc3)
+*/
+.yui3-cssgrids .yui3-d3 {
+ width: 74.923em;
+ *width: 73.05em;
+}
+.yui3-cssgrids .yui3-d3f {
+ width: 974px;
+}
+/*
+Section: Preset Template Rules (.yui3-t[1-6])
+*/
+/*
+Subsection: General
+*/
+
+/* to preserve source-order independence for Gecko without breaking IE */
+.yui3-cssgrids .yui3-b {
+ position: relative;
+}
+.yui3-cssgrids .yui3-b {
+ _position: static;
+}
+.yui3-cssgrids .yui3-main .yui3-b {
+ position: static;
+}
+.yui3-cssgrids .yui3-main {
+ width: 100%;
+}
+.yui3-cssgrids .yui3-t1 .yui3-main,
+.yui3-cssgrids .yui3-t2 .yui3-main,
+.yui3-cssgrids .yui3-t3 .yui3-main {
+ float: right;
+ /* IE: preserve layout at narrow widths */
+ margin-left: -25em;
+}
+.yui3-cssgrids .yui3-t4 .yui3-main,
+.yui3-cssgrids .yui3-t5 .yui3-main,
+.yui3-cssgrids .yui3-t6 .yui3-main {
+ float: left;
+ /* IE: preserve layout at narrow widths */
+ margin-right: -25em;
+}
+
+/* Subsection: For Specific Template Presets */
+
+/**
+* Nudge down to get to 13px equivalent for these form elements
+*/
+
+/*
+TODO Create t1-6's that are based on fixed widths
+*/
+/* t1 narrow block = left, equivalent of 160px */
+.yui3-cssgrids .yui3-t1 .yui3-b {
+ float: left;
+ width: 12.30769em;
+ *width: 12.00em;
+}
+.yui3-cssgrids .yui3-t1 .yui3-main .yui3-b {
+ margin-left: 13.30769em;
+ *margin-left:12.975em;
+}
+/* t2 narrow block = left, equivalent of 180px */
+.yui3-cssgrids .yui3-t2 .yui3-b {
+ float: left;
+ width: 13.84615em;
+ *width: 13.50em;
+}
+.yui3-cssgrids .yui3-t2 .yui3-main .yui3-b {
+ margin-left: 14.84615em;
+ *margin-left: 14.475em;
+}
+/* t3 narrow block = left, equivalent of 300px */
+.yui3-cssgrids .yui3-t3 .yui3-b {
+ float: left;
+ width: 23.0769em;
+ *width: 22.50em;
+}
+.yui3-cssgrids .yui3-t3 .yui3-main .yui3-b {
+ margin-left: 24.0769em;
+ *margin-left: 23.475em;
+}
+/* t4 narrow block = right, equivalent of 180px */
+.yui3-cssgrids .yui3-t4 .yui3-b {
+ float: right;
+ width: 13.8456em;
+ *width: 13.50em;
+}
+.yui3-cssgrids .yui3-t4 .yui3-main .yui3-b {
+ margin-right: 14.8456em;
+ *margin-right: 14.475em;
+}
+/* t5 narrow block = right, equivalent of 240px */
+.yui3-cssgrids .yui3-t5 .yui3-b {
+ float: right;
+ width: 18.4615em;
+ *width: 18.00em;
+}
+.yui3-cssgrids .yui3-t5 .yui3-main .yui3-b {
+ margin-right: 19.4615em;
+ *margin-right: 18.975em;
+}
+/* t6 narrow block = equivalent of 300px */
+.yui3-cssgrids .yui3-t6 .yui3-b {
+ float: right;
+ width: 23.0769em;
+ *width: 22.50em;
+}
+.yui3-cssgrids .yui3-t6 .yui3-main .yui3-b {
+ margin-right: 24.0769em;
+ *margin-right: 23.475em;
+}
+
+.yui3-cssgrids .yui3-main .yui3-b {
+ float: none;
+ width: auto;
+}
+
+/*
+Section: Grids and Nesting Grids
+*/
+
+/*
+Subsection: Children generally take half the available space
+*/
+
+.yui3-cssgrids .yui3-gb .yui3-u,
+.yui3-cssgrids .yui3-g .yui3-gb .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-g,
+.yui3-cssgrids .yui3-gb .yui3-gb,
+.yui3-cssgrids .yui3-gb .yui3-gc,
+.yui3-cssgrids .yui3-gb .yui3-gd,
+.yui3-cssgrids .yui3-gb .yui3-ge,
+.yui3-cssgrids .yui3-gb .yui3-gf,
+.yui3-cssgrids .yui3-gc .yui3-u,
+.yui3-cssgrids .yui3-gc .yui3-g,
+.yui3-cssgrids .yui3-gd .yui3-u {
+ float: left;
+}
+
+/*Float units (and sub grids) to the right */
+.yui3-cssgrids .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-g .yui3-g,
+.yui3-cssgrids .yui3-g .yui3-gb,
+.yui3-cssgrids .yui3-g .yui3-gc,
+.yui3-cssgrids .yui3-g .yui3-gd,
+.yui3-cssgrids .yui3-g .yui3-ge,
+.yui3-cssgrids .yui3-g .yui3-gf,
+.yui3-cssgrids .yui3-gc .yui3-u,
+.yui3-cssgrids .yui3-gd .yui3-g,
+.yui3-cssgrids .yui3-g .yui3-gc .yui3-u,
+.yui3-cssgrids .yui3-ge .yui3-u,
+.yui3-cssgrids .yui3-ge .yui3-g,
+.yui3-cssgrids .yui3-gf .yui3-g,
+.yui3-cssgrids .yui3-gf .yui3-u {
+ float: right;
+}
+
+/*Float units (and sub grids) to the left */
+.yui3-cssgrids .yui3-g div.first,
+.yui3-cssgrids .yui3-gb div.first,
+.yui3-cssgrids .yui3-gc div.first,
+.yui3-cssgrids .yui3-gd div.first,
+.yui3-cssgrids .yui3-ge div.first,
+.yui3-cssgrids .yui3-gf div.first,
+.yui3-cssgrids .yui3-g .yui3-gc div.first,
+.yui3-cssgrids .yui3-g .yui3-ge div.first,
+.yui3-cssgrids .yui3-gc div.first div.first {
+ float: left;
+}
+
+.yui3-cssgrids .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-g .yui3-g,
+.yui3-cssgrids .yui3-g .yui3-gb,
+.yui3-cssgrids .yui3-g .yui3-gc,
+.yui3-cssgrids .yui3-g .yui3-gd,
+.yui3-cssgrids .yui3-g .yui3-ge,
+.yui3-cssgrids .yui3-g .yui3-gf {
+ width: 49.1%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-u,
+.yui3-cssgrids .yui3-g .yui3-gb .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-g,
+.yui3-cssgrids .yui3-gb .yui3-gb,
+.yui3-cssgrids .yui3-gb .yui3-gc,
+.yui3-cssgrids .yui3-gb .yui3-gd,
+.yui3-cssgrids .yui3-gb .yui3-ge,
+.yui3-cssgrids .yui3-gb .yui3-gf,
+.yui3-cssgrids .yui3-gc .yui3-u,
+.yui3-cssgrids .yui3-gc .yui3-g,
+.yui3-cssgrids .yui3-gd .yui3-u {
+ width: 32%;
+ margin-left: 2.0%;
+}
+
+/* Give IE some extra breathing room for 1/3-based rounding issues */
+.yui3-cssgrids .yui3-gb .yui3-u {
+ *width: 31.8%;
+ *margin-left: 1.9%;
+}
+
+.yui3-cssgrids .yui3-gc div.first,
+.yui3-cssgrids .yui3-gd .yui3-u {
+ width: 66%;
+ _width: 65.7%;
+}
+.yui3-cssgrids .yui3-gd div.first {
+ width: 32%;
+ _width: 31.5%;
+}
+
+.yui3-cssgrids .yui3-ge div.first,
+.yui3-cssgrids .yui3-gf .yui3-u {
+ width: 74.2%;
+ _width: 74%;
+}
+
+.yui3-cssgrids .yui3-ge .yui3-u,
+.yui3-cssgrids .yui3-gf div.first {
+ width: 24%;
+ _width: 23.8%;
+}
+
+.yui3-cssgrids .yui3-g .yui3-gb div.first,
+.yui3-cssgrids .yui3-gb div.first,
+.yui3-cssgrids .yui3-gc div.first,
+.yui3-cssgrids .yui3-gd div.first {
+ margin-left: 0;
+}
+
+/*
+Section: Deep Nesting
+*/
+.yui3-cssgrids .yui3-g .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-gc .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-gd .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-ge .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-gf .yui3-g .yui3-u {
+ width: 49%;
+ *width: 48.1%;
+ *margin-left: 0;
+}
+
+.yui3-cssgrids .yui3-g .yui3-gb div.first,
+.yui3-cssgrids .yui3-gb .yui3-gb div.first {
+ *margin-right: 0;
+ *width: 32%;
+ _width: 31.7%;
+}
+
+.yui3-cssgrids .yui3-g .yui3-gc div.first,
+.yui3-cssgrids .yui3-gd .yui3-g {
+ width: 66%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-g div.first {
+ *margin-right: 4%;
+ _margin-right: 1.3%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-gc div.first,
+.yui3-cssgrids .yui3-gb .yui3-gd div.first {
+ *margin-right: 0;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-gb .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-gc .yui3-u {
+ *margin-left: 1.8%;
+ _margin-left: 4%;
+}
+
+.yui3-cssgrids .yui3-g .yui3-gb .yui3-u {
+ _margin-left: 1.0%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-gd .yui3-u {
+ *width: 66%;
+ _width: 61.2%;
+}
+.yui3-cssgrids .yui3-gb .yui3-gd div.first {
+ *width: 31%;
+ _width: 29.5%;
+}
+
+.yui3-cssgrids .yui3-g .yui3-gc .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-gc .yui3-u {
+ width: 32%;
+ _float: right;
+ margin-right: 0;
+ _margin-left: 0;
+}
+.yui3-cssgrids .yui3-gb .yui3-gc div.first {
+ width: 66%;
+ *float: left;
+ *margin-left: 0;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-ge .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-gf .yui3-u {
+ margin: 0;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-gb .yui3-u {
+ _margin-left: .7%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-g div.first,
+.yui3-cssgrids .yui3-gb .yui3-gb div.first {
+ *margin-left:0;
+}
+
+.yui3-cssgrids .yui3-gc .yui3-g .yui3-u,
+.yui3-cssgrids .yui3-gd .yui3-g .yui3-u {
+ *width: 48.1%;
+ *margin-left: 0;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-gd div.first {
+ width: 32%;
+}
+.yui3-cssgrids .yui3-g .yui3-gd div.first {
+ _width: 29.9%;
+}
+
+.yui3-cssgrids .yui3-ge .yui3-g {
+ width: 24%;
+}
+.yui3-cssgrids .yui3-gf .yui3-g {
+ width: 74.2%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-ge div.yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-gf div.yui3-u {
+ float: right;
+}
+.yui3-cssgrids .yui3-gb .yui3-ge div.first,
+.yui3-cssgrids .yui3-gb .yui3-gf div.first {
+ float: left;
+}
+
+/* Width Accommodation for Nested Contexts */
+.yui3-cssgrids .yui3-gb .yui3-ge .yui3-u,
+.yui3-cssgrids .yui3-gb .yui3-gf div.first {
+ *width: 24%;
+ _width: 20%;
+}
+
+/* Width Accommodation for Nested Contexts */
+
+.yui3-cssgrids .yui3-gc .yui3-gf .yui3-u {
+ width: 74%;
+ _width: 73%;
+}
+
+.yui3-cssgrids .yui3-gc .yui3-gf div.first {
+ width: 24%;
+}
+
+.yui3-cssgrids .yui3-gb .yui3-ge div.first,
+.yui3-cssgrids .yui3-gb .yui3-gf .yui3-u {
+ *width: 73.5%;
+ _width: 65.5%;
+}
+
+/* Patch for GD within GE */
+.yui3-cssgrids .yui3-ge div.first .yui3-gd .yui3-u {
+ width: 65%;
+}
+.yui3-cssgrids .yui3-ge div.first .yui3-gd div.first {
+ width: 32%;
+}
+
+/*
+Section: Clearing. zoom for IE, :after for others
+*/
+
+.yui3-cssgrids #bd:after,
+.yui3-cssgrids .yui3-g:after,
+.yui3-cssgrids .yui3-gb:after,
+.yui3-cssgrids .yui3-gc:after,
+.yui3-cssgrids .yui3-gd:after,
+.yui3-cssgrids .yui3-ge:after,
+.yui3-cssgrids .yui3-gf:after,
+.yui3-cssgrids .yui3-t1:after,
+.yui3-cssgrids .yui3-t2:after,
+.yui3-cssgrids .yui3-t3:after,
+.yui3-cssgrids .yui3-t4:after,
+.yui3-cssgrids .yui3-t5:after,
+.yui3-cssgrids .yui3-t6:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+}
+.yui3-cssgrids #bd,
+.yui3-cssgrids .yui3-g,
+.yui3-cssgrids .yui3-gb,
+.yui3-cssgrids .yui3-gc,
+.yui3-cssgrids .yui3-gd,
+.yui3-cssgrids .yui3-ge,
+.yui3-cssgrids .yui3-gf,
+.yui3-cssgrids .yui3-t1,
+.yui3-cssgrids .yui3-t2,
+.yui3-cssgrids .yui3-t3,
+.yui3-cssgrids .yui3-t4,
+.yui3-cssgrids .yui3-t5,
+.yui3-cssgrids .yui3-t6 {
+ zoom: 1;
+}
diff --git a/js/yui3/cssgrids-units/cssgrids-units-min.css b/js/yui3/cssgrids-units/cssgrids-units-min.css
new file mode 100644
index 000000000..8544d0a78
--- /dev/null
+++ b/js/yui3/cssgrids-units/cssgrids-units-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-u-1,.yui3-u-1-2,.yui3-u-1-3,.yui3-u-2-3,.yui3-u-1-4,.yui3-u-3-4,.yui3-u-1-5,.yui3-u-2-5,.yui3-u-3-5,.yui3-u-4-5,.yui3-u-1-6,.yui3-u-5-6,.yui3-u-1-8,.yui3-u-3-8,.yui3-u-5-8,.yui3-u-7-8,.yui3-u-1-12,.yui3-u-5-12,.yui3-u-7-12,.yui3-u-11-12,.yui3-u-1-24,.yui3-u-5-24,.yui3-u-7-24,.yui3-u-11-24,.yui3-u-13-24,.yui3-u-17-24,.yui3-u-19-24,.yui3-u-23-24{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}.yui3-u-1{display:block}.yui3-u-1-2{width:50%}.yui3-u-1-3{width:33.33333%}.yui3-u-2-3{width:66.66666%}.yui3-u-1-4{width:25%}.yui3-u-3-4{width:75%}.yui3-u-1-5{width:20%}.yui3-u-2-5{width:40%}.yui3-u-3-5{width:60%}.yui3-u-4-5{width:80%}.yui3-u-1-6{width:16.656%}.yui3-u-5-6{width:83.33%}.yui3-u-1-8{width:12.5%}.yui3-u-3-8{width:37.5%}.yui3-u-5-8{width:62.5%}.yui3-u-7-8{width:87.5%}.yui3-u-1-12{width:8.3333%}.yui3-u-5-12{width:41.6666%}.yui3-u-7-12{width:58.3333%}.yui3-u-11-12{width:91.6666%}.yui3-u-1-24{width:4.1666%}.yui3-u-5-24{width:20.8333%}.yui3-u-7-24{width:29.1666%}.yui3-u-11-24{width:45.8333%}.yui3-u-13-24{width:54.1666%}.yui3-u-17-24{width:70.8333%}.yui3-u-19-24{width:79.1666%}.yui3-u-23-24{width:95.8333%}#yui3-css-stamp.cssgrids-units{display:none}
diff --git a/js/yui3/cssgrids-units/cssgrids-units.css b/js/yui3/cssgrids-units/cssgrids-units.css
new file mode 100644
index 000000000..60e4ccd3b
--- /dev/null
+++ b/js/yui3/cssgrids-units/cssgrids-units.css
@@ -0,0 +1,155 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-u-1,
+.yui3-u-1-2,
+.yui3-u-1-3,
+.yui3-u-2-3,
+.yui3-u-1-4,
+.yui3-u-3-4,
+.yui3-u-1-5,
+.yui3-u-2-5,
+.yui3-u-3-5,
+.yui3-u-4-5,
+.yui3-u-1-6,
+.yui3-u-5-6,
+.yui3-u-1-8,
+.yui3-u-3-8,
+.yui3-u-5-8,
+.yui3-u-7-8,
+.yui3-u-1-12,
+.yui3-u-5-12,
+.yui3-u-7-12,
+.yui3-u-11-12,
+.yui3-u-1-24,
+.yui3-u-5-24,
+.yui3-u-7-24,
+.yui3-u-11-24,
+.yui3-u-13-24,
+.yui3-u-17-24,
+.yui3-u-19-24,
+.yui3-u-23-24 {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+
+.yui3-u-1 {
+ display: block;
+}
+
+.yui3-u-1-2 {
+ width: 50%;
+}
+
+.yui3-u-1-3 {
+ width: 33.33333%;
+}
+
+.yui3-u-2-3 {
+ width: 66.66666%;
+}
+
+.yui3-u-1-4 {
+ width: 25%;
+}
+
+.yui3-u-3-4 {
+ width: 75%;
+}
+
+.yui3-u-1-5 {
+ width: 20%;
+}
+
+.yui3-u-2-5 {
+ width: 40%;
+}
+
+.yui3-u-3-5 {
+ width: 60%;
+}
+
+.yui3-u-4-5 {
+ width: 80%;
+}
+
+.yui3-u-1-6 {
+ width: 16.656%;
+}
+
+.yui3-u-5-6 {
+ width: 83.33%;
+}
+
+.yui3-u-1-8 {
+ width: 12.5%;
+}
+
+.yui3-u-3-8 {
+ width: 37.5%;
+}
+
+.yui3-u-5-8 {
+ width: 62.5%;
+}
+
+.yui3-u-7-8 {
+ width: 87.5%;
+}
+
+.yui3-u-1-12 {
+ width: 8.3333%;
+}
+
+.yui3-u-5-12 {
+ width: 41.6666%;
+}
+
+.yui3-u-7-12 {
+ width: 58.3333%;
+}
+
+.yui3-u-11-12 {
+ width: 91.6666%;
+}
+
+.yui3-u-1-24 {
+ width: 4.1666%;
+}
+
+.yui3-u-5-24 {
+ width: 20.8333%;
+}
+
+.yui3-u-7-24 {
+ width: 29.1666%;
+}
+
+.yui3-u-11-24 {
+ width: 45.8333%;
+}
+
+.yui3-u-13-24 {
+ width: 54.1666%;
+}
+
+.yui3-u-17-24 {
+ width: 70.8333%;
+}
+
+.yui3-u-19-24 {
+ width: 79.1666%;
+}
+
+.yui3-u-23-24 {
+ width: 95.8333%;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssgrids-units { display: none; }
diff --git a/js/yui3/cssgrids/cssgrids-min.css b/js/yui3/cssgrids/cssgrids-min.css
new file mode 100644
index 000000000..cfebbcade
--- /dev/null
+++ b/js/yui3/cssgrids/cssgrids-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g{letter-spacing:-0.31em;*letter-spacing:normal;word-spacing:-0.43em}.yui3-u{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}.yui3-u-1,.yui3-u-1-2,.yui3-u-1-3,.yui3-u-2-3,.yui3-u-1-4,.yui3-u-3-4,.yui3-u-1-5,.yui3-u-2-5,.yui3-u-3-5,.yui3-u-4-5,.yui3-u-1-6,.yui3-u-5-6,.yui3-u-1-8,.yui3-u-3-8,.yui3-u-5-8,.yui3-u-7-8,.yui3-u-1-12,.yui3-u-5-12,.yui3-u-7-12,.yui3-u-11-12,.yui3-u-1-24,.yui3-u-5-24,.yui3-u-7-24,.yui3-u-11-24,.yui3-u-13-24,.yui3-u-17-24,.yui3-u-19-24,.yui3-u-23-24{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}.yui3-u-1{display:block}.yui3-u-1-2{width:50%}.yui3-u-1-3{width:33.33333%}.yui3-u-2-3{width:66.66666%}.yui3-u-1-4{width:25%}.yui3-u-3-4{width:75%}.yui3-u-1-5{width:20%}.yui3-u-2-5{width:40%}.yui3-u-3-5{width:60%}.yui3-u-4-5{width:80%}.yui3-u-1-6{width:16.656%}.yui3-u-5-6{width:83.33%}.yui3-u-1-8{width:12.5%}.yui3-u-3-8{width:37.5%}.yui3-u-5-8{width:62.5%}.yui3-u-7-8{width:87.5%}.yui3-u-1-12{width:8.3333%}.yui3-u-5-12{width:41.6666%}.yui3-u-7-12{width:58.3333%}.yui3-u-11-12{width:91.6666%}.yui3-u-1-24{width:4.1666%}.yui3-u-5-24{width:20.8333%}.yui3-u-7-24{width:29.1666%}.yui3-u-11-24{width:45.8333%}.yui3-u-13-24{width:54.1666%}.yui3-u-17-24{width:70.8333%}.yui3-u-19-24{width:79.1666%}.yui3-u-23-24{width:95.8333%}#yui3-css-stamp.cssgrids{display:none}
diff --git a/js/yui3/cssgrids/cssgrids.css b/js/yui3/cssgrids/cssgrids.css
new file mode 100644
index 000000000..d133d8a14
--- /dev/null
+++ b/js/yui3/cssgrids/cssgrids.css
@@ -0,0 +1,168 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g {
+ letter-spacing: -0.31em; /* webkit: collapse white-space between units */
+ *letter-spacing: normal; /* reset IE < 8 */
+ word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
+}
+
+.yui3-u {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+.yui3-u-1,
+.yui3-u-1-2,
+.yui3-u-1-3,
+.yui3-u-2-3,
+.yui3-u-1-4,
+.yui3-u-3-4,
+.yui3-u-1-5,
+.yui3-u-2-5,
+.yui3-u-3-5,
+.yui3-u-4-5,
+.yui3-u-1-6,
+.yui3-u-5-6,
+.yui3-u-1-8,
+.yui3-u-3-8,
+.yui3-u-5-8,
+.yui3-u-7-8,
+.yui3-u-1-12,
+.yui3-u-5-12,
+.yui3-u-7-12,
+.yui3-u-11-12,
+.yui3-u-1-24,
+.yui3-u-5-24,
+.yui3-u-7-24,
+.yui3-u-11-24,
+.yui3-u-13-24,
+.yui3-u-17-24,
+.yui3-u-19-24,
+.yui3-u-23-24 {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+
+.yui3-u-1 {
+ display: block;
+}
+
+.yui3-u-1-2 {
+ width: 50%;
+}
+
+.yui3-u-1-3 {
+ width: 33.33333%;
+}
+
+.yui3-u-2-3 {
+ width: 66.66666%;
+}
+
+.yui3-u-1-4 {
+ width: 25%;
+}
+
+.yui3-u-3-4 {
+ width: 75%;
+}
+
+.yui3-u-1-5 {
+ width: 20%;
+}
+
+.yui3-u-2-5 {
+ width: 40%;
+}
+
+.yui3-u-3-5 {
+ width: 60%;
+}
+
+.yui3-u-4-5 {
+ width: 80%;
+}
+
+.yui3-u-1-6 {
+ width: 16.656%;
+}
+
+.yui3-u-5-6 {
+ width: 83.33%;
+}
+
+.yui3-u-1-8 {
+ width: 12.5%;
+}
+
+.yui3-u-3-8 {
+ width: 37.5%;
+}
+
+.yui3-u-5-8 {
+ width: 62.5%;
+}
+
+.yui3-u-7-8 {
+ width: 87.5%;
+}
+
+.yui3-u-1-12 {
+ width: 8.3333%;
+}
+
+.yui3-u-5-12 {
+ width: 41.6666%;
+}
+
+.yui3-u-7-12 {
+ width: 58.3333%;
+}
+
+.yui3-u-11-12 {
+ width: 91.6666%;
+}
+
+.yui3-u-1-24 {
+ width: 4.1666%;
+}
+
+.yui3-u-5-24 {
+ width: 20.8333%;
+}
+
+.yui3-u-7-24 {
+ width: 29.1666%;
+}
+
+.yui3-u-11-24 {
+ width: 45.8333%;
+}
+
+.yui3-u-13-24 {
+ width: 54.1666%;
+}
+
+.yui3-u-17-24 {
+ width: 70.8333%;
+}
+
+.yui3-u-19-24 {
+ width: 79.1666%;
+}
+
+.yui3-u-23-24 {
+ width: 95.8333%;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssgrids { display: none; }
diff --git a/js/yui3/cssgrids/grids-min.css b/js/yui3/cssgrids/grids-min.css
new file mode 100644
index 000000000..d427c751f
--- /dev/null
+++ b/js/yui3/cssgrids/grids-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g{letter-spacing:-0.31em;*letter-spacing:normal;word-spacing:-0.43em}.yui3-u{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}.yui3-u-1,.yui3-u-1-2,.yui3-u-1-3,.yui3-u-2-3,.yui3-u-1-4,.yui3-u-3-4,.yui3-u-1-5,.yui3-u-2-5,.yui3-u-3-5,.yui3-u-4-5,.yui3-u-1-6,.yui3-u-5-6,.yui3-u-1-8,.yui3-u-3-8,.yui3-u-5-8,.yui3-u-7-8,.yui3-u-1-12,.yui3-u-5-12,.yui3-u-7-12,.yui3-u-11-12,.yui3-u-1-24,.yui3-u-5-24,.yui3-u-7-24,.yui3-u-11-24,.yui3-u-13-24,.yui3-u-17-24,.yui3-u-19-24,.yui3-u-23-24{display:inline-block;zoom:1;*display:inline;letter-spacing:normal;word-spacing:normal;vertical-align:top}.yui3-u-1{display:block}.yui3-u-1-2{width:50%}.yui3-u-1-3{width:33.33333%}.yui3-u-2-3{width:66.66666%}.yui3-u-1-4{width:25%}.yui3-u-3-4{width:75%}.yui3-u-1-5{width:20%}.yui3-u-2-5{width:40%}.yui3-u-3-5{width:60%}.yui3-u-4-5{width:80%}.yui3-u-1-6{width:16.656%}.yui3-u-5-6{width:83.33%}.yui3-u-1-8{width:12.5%}.yui3-u-3-8{width:37.5%}.yui3-u-5-8{width:62.5%}.yui3-u-7-8{width:87.5%}.yui3-u-1-12{width:8.3333%}.yui3-u-5-12{width:41.6666%}.yui3-u-7-12{width:58.3333%}.yui3-u-11-12{width:91.6666%}.yui3-u-1-24{width:4.1666%}.yui3-u-5-24{width:20.8333%}.yui3-u-7-24{width:29.1666%}.yui3-u-11-24{width:45.8333%}.yui3-u-13-24{width:54.1666%}.yui3-u-17-24{width:70.8333%}.yui3-u-19-24{width:79.1666%}.yui3-u-23-24{width:95.8333%}#yui3-css-stamp.cssgrids{display:none} \ No newline at end of file
diff --git a/js/yui3/cssgrids/grids.css b/js/yui3/cssgrids/grids.css
new file mode 100644
index 000000000..9db8cef37
--- /dev/null
+++ b/js/yui3/cssgrids/grids.css
@@ -0,0 +1,167 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-g {
+ letter-spacing: -0.31em; /* webkit: collapse white-space between units */
+ *letter-spacing: normal; /* reset IE < 8 */
+ word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
+}
+
+.yui3-u {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+.yui3-u-1,
+.yui3-u-1-2,
+.yui3-u-1-3,
+.yui3-u-2-3,
+.yui3-u-1-4,
+.yui3-u-3-4,
+.yui3-u-1-5,
+.yui3-u-2-5,
+.yui3-u-3-5,
+.yui3-u-4-5,
+.yui3-u-1-6,
+.yui3-u-5-6,
+.yui3-u-1-8,
+.yui3-u-3-8,
+.yui3-u-5-8,
+.yui3-u-7-8,
+.yui3-u-1-12,
+.yui3-u-5-12,
+.yui3-u-7-12,
+.yui3-u-11-12,
+.yui3-u-1-24,
+.yui3-u-5-24,
+.yui3-u-7-24,
+.yui3-u-11-24,
+.yui3-u-13-24,
+.yui3-u-17-24,
+.yui3-u-19-24,
+.yui3-u-23-24 {
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+}
+
+.yui3-u-1 {
+ display: block;
+}
+
+.yui3-u-1-2 {
+ width: 50%;
+}
+
+.yui3-u-1-3 {
+ width: 33.33333%;
+}
+
+.yui3-u-2-3 {
+ width: 66.66666%;
+}
+
+.yui3-u-1-4 {
+ width: 25%;
+}
+
+.yui3-u-3-4 {
+ width: 75%;
+}
+
+.yui3-u-1-5 {
+ width: 20%;
+}
+
+.yui3-u-2-5 {
+ width: 40%;
+}
+
+.yui3-u-3-5 {
+ width: 60%;
+}
+
+.yui3-u-4-5 {
+ width: 80%;
+}
+
+.yui3-u-1-6 {
+ width: 16.656%;
+}
+
+.yui3-u-5-6 {
+ width: 83.33%;
+}
+
+.yui3-u-1-8 {
+ width: 12.5%;
+}
+
+.yui3-u-3-8 {
+ width: 37.5%;
+}
+
+.yui3-u-5-8 {
+ width: 62.5%;
+}
+
+.yui3-u-7-8 {
+ width: 87.5%;
+}
+
+.yui3-u-1-12 {
+ width: 8.3333%;
+}
+
+.yui3-u-5-12 {
+ width: 41.6666%;
+}
+
+.yui3-u-7-12 {
+ width: 58.3333%;
+}
+
+.yui3-u-11-12 {
+ width: 91.6666%;
+}
+
+.yui3-u-1-24 {
+ width: 4.1666%;
+}
+
+.yui3-u-5-24 {
+ width: 20.8333%;
+}
+
+.yui3-u-7-24 {
+ width: 29.1666%;
+}
+
+.yui3-u-11-24 {
+ width: 45.8333%;
+}
+
+.yui3-u-13-24 {
+ width: 54.1666%;
+}
+
+.yui3-u-17-24 {
+ width: 70.8333%;
+}
+
+.yui3-u-19-24 {
+ width: 79.1666%;
+}
+
+.yui3-u-23-24 {
+ width: 95.8333%;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssgrids { display: none; }
diff --git a/js/yui3/cssreset-context/cssreset-context-min.css b/js/yui3/cssreset-context/cssreset-context-min.css
new file mode 100644
index 000000000..49f047d78
--- /dev/null
+++ b/js/yui3/cssreset-context/cssreset-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssreset html{color:#000;background:#FFF}.yui3-cssreset body,.yui3-cssreset div,.yui3-cssreset dl,.yui3-cssreset dt,.yui3-cssreset dd,.yui3-cssreset ul,.yui3-cssreset ol,.yui3-cssreset li,.yui3-cssreset h1,.yui3-cssreset h2,.yui3-cssreset h3,.yui3-cssreset h4,.yui3-cssreset h5,.yui3-cssreset h6,.yui3-cssreset pre,.yui3-cssreset code,.yui3-cssreset form,.yui3-cssreset fieldset,.yui3-cssreset legend,.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset p,.yui3-cssreset blockquote,.yui3-cssreset th,.yui3-cssreset td{margin:0;padding:0}.yui3-cssreset table{border-collapse:collapse;border-spacing:0}.yui3-cssreset fieldset,.yui3-cssreset img{border:0}.yui3-cssreset address,.yui3-cssreset caption,.yui3-cssreset cite,.yui3-cssreset code,.yui3-cssreset dfn,.yui3-cssreset em,.yui3-cssreset strong,.yui3-cssreset th,.yui3-cssreset var{font-style:normal;font-weight:normal}.yui3-cssreset ol,.yui3-cssreset ul{list-style:none}.yui3-cssreset caption,.yui3-cssreset th{text-align:left}.yui3-cssreset h1,.yui3-cssreset h2,.yui3-cssreset h3,.yui3-cssreset h4,.yui3-cssreset h5,.yui3-cssreset h6{font-size:100%;font-weight:normal}.yui3-cssreset q:before,.yui3-cssreset q:after{content:''}.yui3-cssreset abbr,.yui3-cssreset acronym{border:0;font-variant:normal}.yui3-cssreset sup{vertical-align:text-top}.yui3-cssreset sub{vertical-align:text-bottom}.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset select{font-family:inherit;font-size:inherit;font-weight:inherit}.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset select{*font-size:100%}.yui3-cssreset legend{color:#000}#yui3-css-stamp.cssreset-context{display:none}
diff --git a/js/yui3/cssreset-context/cssreset-context.css b/js/yui3/cssreset-context/cssreset-context.css
new file mode 100644
index 000000000..a5ade21b9
--- /dev/null
+++ b/js/yui3/cssreset-context/cssreset-context.css
@@ -0,0 +1,127 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/*e
+ TODO will need to remove settings on HTML since we can't namespace it.
+ TODO with the prefix, should I group by selector or property for weight savings?
+*/
+.yui3-cssreset html{
+ color:#000;
+ background:#FFF;
+}
+/*
+ TODO remove settings on BODY since we can't namespace it.
+*/
+/*
+ TODO test putting a class on HEAD.
+ - Fails on FF.
+*/
+.yui3-cssreset body,
+.yui3-cssreset div,
+.yui3-cssreset dl,
+.yui3-cssreset dt,
+.yui3-cssreset dd,
+.yui3-cssreset ul,
+.yui3-cssreset ol,
+.yui3-cssreset li,
+.yui3-cssreset h1,
+.yui3-cssreset h2,
+.yui3-cssreset h3,
+.yui3-cssreset h4,
+.yui3-cssreset h5,
+.yui3-cssreset h6,
+.yui3-cssreset pre,
+.yui3-cssreset code,
+.yui3-cssreset form,
+.yui3-cssreset fieldset,
+.yui3-cssreset legend,
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset p,
+.yui3-cssreset blockquote,
+.yui3-cssreset th,
+.yui3-cssreset td {
+ margin:0;
+ padding:0;
+}
+.yui3-cssreset table {
+ border-collapse:collapse;
+ border-spacing:0;
+}
+.yui3-cssreset fieldset,
+.yui3-cssreset img {
+ border:0;
+}
+/*
+ TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...
+*/
+.yui3-cssreset address,
+.yui3-cssreset caption,
+.yui3-cssreset cite,
+.yui3-cssreset code,
+.yui3-cssreset dfn,
+.yui3-cssreset em,
+.yui3-cssreset strong,
+.yui3-cssreset th,
+.yui3-cssreset var {
+ font-style:normal;
+ font-weight:normal;
+}
+
+.yui3-cssreset ol,
+.yui3-cssreset ul {
+ list-style:none;
+}
+
+.yui3-cssreset caption,
+.yui3-cssreset th {
+ text-align:left;
+}
+.yui3-cssreset h1,
+.yui3-cssreset h2,
+.yui3-cssreset h3,
+.yui3-cssreset h4,
+.yui3-cssreset h5,
+.yui3-cssreset h6 {
+ font-size:100%;
+ font-weight:normal;
+}
+.yui3-cssreset q:before,
+.yui3-cssreset q:after {
+ content:'';
+}
+.yui3-cssreset abbr,
+.yui3-cssreset acronym {
+ border:0;
+ font-variant:normal;
+}
+/* to preserve line-height and selector appearance */
+.yui3-cssreset sup {
+ vertical-align:text-top;
+}
+.yui3-cssreset sub {
+ vertical-align:text-bottom;
+}
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset select {
+ font-family:inherit;
+ font-size:inherit;
+ font-weight:inherit;
+}
+/*to enable resizing for IE*/
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset select {
+ *font-size:100%;
+}
+/*because legend doesn't inherit in IE */
+.yui3-cssreset legend {
+ color:#000;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssreset-context { display: none; }
diff --git a/js/yui3/cssreset-context/reset-context-min.css b/js/yui3/cssreset-context/reset-context-min.css
new file mode 100644
index 000000000..90ce55dff
--- /dev/null
+++ b/js/yui3/cssreset-context/reset-context-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-cssreset html{color:#000;background:#FFF}.yui3-cssreset body,.yui3-cssreset div,.yui3-cssreset dl,.yui3-cssreset dt,.yui3-cssreset dd,.yui3-cssreset ul,.yui3-cssreset ol,.yui3-cssreset li,.yui3-cssreset h1,.yui3-cssreset h2,.yui3-cssreset h3,.yui3-cssreset h4,.yui3-cssreset h5,.yui3-cssreset h6,.yui3-cssreset pre,.yui3-cssreset code,.yui3-cssreset form,.yui3-cssreset fieldset,.yui3-cssreset legend,.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset p,.yui3-cssreset blockquote,.yui3-cssreset th,.yui3-cssreset td{margin:0;padding:0}.yui3-cssreset table{border-collapse:collapse;border-spacing:0}.yui3-cssreset fieldset,.yui3-cssreset img{border:0}.yui3-cssreset address,.yui3-cssreset caption,.yui3-cssreset cite,.yui3-cssreset code,.yui3-cssreset dfn,.yui3-cssreset em,.yui3-cssreset strong,.yui3-cssreset th,.yui3-cssreset var{font-style:normal;font-weight:normal}.yui3-cssreset ol,.yui3-cssreset ul{list-style:none}.yui3-cssreset caption,.yui3-cssreset th{text-align:left}.yui3-cssreset h1,.yui3-cssreset h2,.yui3-cssreset h3,.yui3-cssreset h4,.yui3-cssreset h5,.yui3-cssreset h6{font-size:100%;font-weight:normal}.yui3-cssreset q:before,.yui3-cssreset q:after{content:''}.yui3-cssreset abbr,.yui3-cssreset acronym{border:0;font-variant:normal}.yui3-cssreset sup{vertical-align:text-top}.yui3-cssreset sub{vertical-align:text-bottom}.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset select{font-family:inherit;font-size:inherit;font-weight:inherit}.yui3-cssreset input,.yui3-cssreset textarea,.yui3-cssreset select{*font-size:100%}.yui3-cssreset legend{color:#000}#yui3-css-stamp.cssreset-context{display:none} \ No newline at end of file
diff --git a/js/yui3/cssreset-context/reset-context.css b/js/yui3/cssreset-context/reset-context.css
new file mode 100644
index 000000000..13e8b4892
--- /dev/null
+++ b/js/yui3/cssreset-context/reset-context.css
@@ -0,0 +1,126 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/*e
+ TODO will need to remove settings on HTML since we can't namespace it.
+ TODO with the prefix, should I group by selector or property for weight savings?
+*/
+.yui3-cssreset html{
+ color:#000;
+ background:#FFF;
+}
+/*
+ TODO remove settings on BODY since we can't namespace it.
+*/
+/*
+ TODO test putting a class on HEAD.
+ - Fails on FF.
+*/
+.yui3-cssreset body,
+.yui3-cssreset div,
+.yui3-cssreset dl,
+.yui3-cssreset dt,
+.yui3-cssreset dd,
+.yui3-cssreset ul,
+.yui3-cssreset ol,
+.yui3-cssreset li,
+.yui3-cssreset h1,
+.yui3-cssreset h2,
+.yui3-cssreset h3,
+.yui3-cssreset h4,
+.yui3-cssreset h5,
+.yui3-cssreset h6,
+.yui3-cssreset pre,
+.yui3-cssreset code,
+.yui3-cssreset form,
+.yui3-cssreset fieldset,
+.yui3-cssreset legend,
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset p,
+.yui3-cssreset blockquote,
+.yui3-cssreset th,
+.yui3-cssreset td {
+ margin:0;
+ padding:0;
+}
+.yui3-cssreset table {
+ border-collapse:collapse;
+ border-spacing:0;
+}
+.yui3-cssreset fieldset,
+.yui3-cssreset img {
+ border:0;
+}
+/*
+ TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...
+*/
+.yui3-cssreset address,
+.yui3-cssreset caption,
+.yui3-cssreset cite,
+.yui3-cssreset code,
+.yui3-cssreset dfn,
+.yui3-cssreset em,
+.yui3-cssreset strong,
+.yui3-cssreset th,
+.yui3-cssreset var {
+ font-style:normal;
+ font-weight:normal;
+}
+
+.yui3-cssreset ol,
+.yui3-cssreset ul {
+ list-style:none;
+}
+
+.yui3-cssreset caption,
+.yui3-cssreset th {
+ text-align:left;
+}
+.yui3-cssreset h1,
+.yui3-cssreset h2,
+.yui3-cssreset h3,
+.yui3-cssreset h4,
+.yui3-cssreset h5,
+.yui3-cssreset h6 {
+ font-size:100%;
+ font-weight:normal;
+}
+.yui3-cssreset q:before,
+.yui3-cssreset q:after {
+ content:'';
+}
+.yui3-cssreset abbr,
+.yui3-cssreset acronym {
+ border:0;
+ font-variant:normal;
+}
+/* to preserve line-height and selector appearance */
+.yui3-cssreset sup {
+ vertical-align:text-top;
+}
+.yui3-cssreset sub {
+ vertical-align:text-bottom;
+}
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset select {
+ font-family:inherit;
+ font-size:inherit;
+ font-weight:inherit;
+}
+/*to enable resizing for IE*/
+.yui3-cssreset input,
+.yui3-cssreset textarea,
+.yui3-cssreset select {
+ *font-size:100%;
+}
+/*because legend doesn't inherit in IE */
+.yui3-cssreset legend {
+ color:#000;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssreset-context { display: none; }
diff --git a/js/yui3/cssreset/cssreset-min.css b/js/yui3/cssreset/cssreset-min.css
new file mode 100644
index 000000000..a0a5ec0c6
--- /dev/null
+++ b/js/yui3/cssreset/cssreset-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{*font-size:100%}legend{color:#000}#yui3-css-stamp.cssreset{display:none}
diff --git a/js/yui3/cssreset/cssreset.css b/js/yui3/cssreset/cssreset.css
new file mode 100644
index 000000000..60abc1564
--- /dev/null
+++ b/js/yui3/cssreset/cssreset.css
@@ -0,0 +1,127 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/*
+ TODO will need to remove settings on HTML since we can't namespace it.
+ TODO with the prefix, should I group by selector or property for weight savings?
+*/
+html{
+ color:#000;
+ background:#FFF;
+}
+/*
+ TODO remove settings on BODY since we can't namespace it.
+*/
+/*
+ TODO test putting a class on HEAD.
+ - Fails on FF.
+*/
+body,
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+pre,
+code,
+form,
+fieldset,
+legend,
+input,
+textarea,
+p,
+blockquote,
+th,
+td {
+ margin:0;
+ padding:0;
+}
+table {
+ border-collapse:collapse;
+ border-spacing:0;
+}
+fieldset,
+img {
+ border:0;
+}
+/*
+ TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...
+*/
+address,
+caption,
+cite,
+code,
+dfn,
+em,
+strong,
+th,
+var {
+ font-style:normal;
+ font-weight:normal;
+}
+
+ol,
+ul {
+ list-style:none;
+}
+
+caption,
+th {
+ text-align:left;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size:100%;
+ font-weight:normal;
+}
+q:before,
+q:after {
+ content:'';
+}
+abbr,
+acronym {
+ border:0;
+ font-variant:normal;
+}
+/* to preserve line-height and selector appearance */
+sup {
+ vertical-align:text-top;
+}
+sub {
+ vertical-align:text-bottom;
+}
+input,
+textarea,
+select {
+ font-family:inherit;
+ font-size:inherit;
+ font-weight:inherit;
+}
+/*to enable resizing for IE*/
+input,
+textarea,
+select {
+ *font-size:100%;
+}
+/*because legend doesn't inherit in IE */
+legend {
+ color:#000;
+}
+
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssreset { display: none; }
diff --git a/js/yui3/cssreset/reset-min.css b/js/yui3/cssreset/reset-min.css
new file mode 100644
index 000000000..0fb4cdb15
--- /dev/null
+++ b/js/yui3/cssreset/reset-min.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{*font-size:100%}legend{color:#000}#yui3-css-stamp.cssreset{display:none} \ No newline at end of file
diff --git a/js/yui3/cssreset/reset.css b/js/yui3/cssreset/reset.css
new file mode 100644
index 000000000..b9ba55396
--- /dev/null
+++ b/js/yui3/cssreset/reset.css
@@ -0,0 +1,126 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/*
+ TODO will need to remove settings on HTML since we can't namespace it.
+ TODO with the prefix, should I group by selector or property for weight savings?
+*/
+html{
+ color:#000;
+ background:#FFF;
+}
+/*
+ TODO remove settings on BODY since we can't namespace it.
+*/
+/*
+ TODO test putting a class on HEAD.
+ - Fails on FF.
+*/
+body,
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+pre,
+code,
+form,
+fieldset,
+legend,
+input,
+textarea,
+p,
+blockquote,
+th,
+td {
+ margin:0;
+ padding:0;
+}
+table {
+ border-collapse:collapse;
+ border-spacing:0;
+}
+fieldset,
+img {
+ border:0;
+}
+/*
+ TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...
+*/
+address,
+caption,
+cite,
+code,
+dfn,
+em,
+strong,
+th,
+var {
+ font-style:normal;
+ font-weight:normal;
+}
+
+ol,
+ul {
+ list-style:none;
+}
+
+caption,
+th {
+ text-align:left;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size:100%;
+ font-weight:normal;
+}
+q:before,
+q:after {
+ content:'';
+}
+abbr,
+acronym {
+ border:0;
+ font-variant:normal;
+}
+/* to preserve line-height and selector appearance */
+sup {
+ vertical-align:text-top;
+}
+sub {
+ vertical-align:text-bottom;
+}
+input,
+textarea,
+select {
+ font-family:inherit;
+ font-size:inherit;
+ font-weight:inherit;
+}
+/*to enable resizing for IE*/
+input,
+textarea,
+select {
+ *font-size:100%;
+}
+/*because legend doesn't inherit in IE */
+legend {
+ color:#000;
+}
+/* YUI CSS Detection Stamp */
+#yui3-css-stamp.cssreset { display: none; }
diff --git a/js/yui3/dataschema-array/dataschema-array-min.js b/js/yui3/dataschema-array/dataschema-array-min.js
new file mode 100644
index 000000000..86a0b4e73
--- /dev/null
+++ b/js/yui3/dataschema-array/dataschema-array-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dataschema-array",function(e,t){var n=e.Lang,r={apply:function(e,t){var i=t,s={results:[],meta:{}};return n.isArray(i)?e&&n.isArray(e.resultFields)?s=r._parseResults.call(this,e.resultFields,i,s):s.results=i:s.error=new Error("Array schema parse failure"),s},_parseResults:function(t,r,i){var s=[],o,u,a,f,l,c,h,p;for(h=r.length-1;h>-1;h--){o={},u=r[h],a=n.isObject(u)&&!n.isFunction(u)?2:n.isArray(u)?1:n.isString(u)?0:-1;if(a>0)for(p=t.length-1;p>-1;p--)f=t[p],l=n.isUndefined(f.key)?f:f.key,c=n.isUndefined(u[l])?u[p]:u[l],o[l]=e.DataSchema.Base.parse.call(this,c,f);else a===0?o=u:o=null;s[h]=o}return i.results=s,i}};e.DataSchema.Array=e.mix(r,e.DataSchema.Base)},"3.7.3",{requires:["dataschema-base"]});
diff --git a/js/yui3/dataschema-base/dataschema-base-min.js b/js/yui3/dataschema-base/dataschema-base-min.js
new file mode 100644
index 000000000..99beb98db
--- /dev/null
+++ b/js/yui3/dataschema-base/dataschema-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dataschema-base",function(e,t){var n=e.Lang,r={apply:function(e,t){return t},parse:function(t,r){if(r.parser){var i=n.isFunction(r.parser)?r.parser:e.Parsers[r.parser+""];i&&(t=i.call(this,t))}return t}};e.namespace("DataSchema").Base=r,e.namespace("Parsers")},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/dataschema-json/dataschema-json-min.js b/js/yui3/dataschema-json/dataschema-json-min.js
new file mode 100644
index 000000000..98a1134c6
--- /dev/null
+++ b/js/yui3/dataschema-json/dataschema-json-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dataschema-json",function(e,t){var n=e.Lang,r=n.isFunction,i=n.isObject,s=n.isArray,o=e.DataSchema.Base,u;u={getPath:function(e){var t=null,n=[],r=0;if(e){e=e.replace(/\[\s*(['"])(.*?)\1\s*\]/g,function(e,t,i){return n[r]=i,".@"+r++}).replace(/\[(\d+)\]/g,function(e,t){return n[r]=parseInt(t,10)|0,".@"+r++}).replace(/^\./,""),t=e.split(".");for(r=t.length-1;r>=0;--r)t[r].charAt(0)==="@"&&(t[r]=n[parseInt(t[r].substr(1),10)])}return t},getLocationValue:function(e,t){var n=0,r=e.length;for(;n<r;n++){if(!(i(t)&&e[n]in t)){t=undefined;break}t=t[e[n]]}return t},apply:function(t,n){var r=n,s={results:[],meta:{}};if(!i(n))try{r=e.JSON.parse(n)}catch(o){return s.error=o,s}return i(r)&&t?(s=u._parseResults.call(this,t,r,s),t.metaFields!==undefined&&(s=u._parseMeta(t.metaFields,r,s))):s.error=new Error("JSON schema parse failure"),s},_parseResults:function(e,t,n){var r=u.getPath,i=u.getLocationValue,o=r(e.resultListLocator),a=o?i(o,t)||t[e.resultListLocator]:t;return s(a)?s(e.resultFields)?n=u._getFieldValues.call(this,e.resultFields,a,n):n.results=a:e.resultListLocator&&(n.results=[],n.error=new Error("JSON results retrieval failure")),n},_getFieldValues:function(t,n,i){var s=[],a=t.length,f,l,c,h,p,d,v,m,g=[],y=[],b=[],w,E;for(f=0;f<a;f++)c=t[f],h=c.key||c,p=c.locator||h,d=u.getPath(p),d&&(d.length===1?g.push({key:h,path:d[0]}):y.push({key:h,path:d,locator:p})),v=r(c.parser)?c.parser:e.Parsers[c.parser+""],v&&b.push({key:h,parser:v});for(f=n.length-1;f>=0;--f){E={},w=n[f];if(w){for(l=y.length-1;l>=0;--l){d=y[l],m=u.getLocationValue(d.path,w);if(m===undefined){m=u.getLocationValue([d.locator],w);if(m!==undefined){g.push({key:d.key,path:d.locator}),y.splice(f,1);continue}}E[d.key]=o.parse.call(this,u.getLocationValue(d.path,w),d)}for(l=g.length-1;l>=0;--l)d=g[l],E[d.key]=o.parse.call(this,w[d.path]===undefined?w[l]:w[d.path],d);for(l=b.length-1;l>=0;--l)h=b[l].key,E[h]=b[l].parser.call(this,E[h]),E[h]===undefined&&(E[h]=null);s[f]=E}}return i.results=s,i},_parseMeta:function(e,t,n){if(i(e)){var r,s;for(r in e)e.hasOwnProperty(r)&&(s=u.getPath(e[r]),s&&t&&(n.meta[r]=u.getLocationValue(s,t)))}else n.error=new Error("JSON meta data retrieval failure");return n}},e.DataSchema.JSON=e.mix(u,o)},"3.7.3",{requires:["dataschema-base","json"]});
diff --git a/js/yui3/dataschema-text/dataschema-text-min.js b/js/yui3/dataschema-text/dataschema-text-min.js
new file mode 100644
index 000000000..eeb504fdd
--- /dev/null
+++ b/js/yui3/dataschema-text/dataschema-text-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dataschema-text",function(e,t){var n=e.Lang,r=n.isString,i=n.isUndefined,s={apply:function(e,t){var n=t,i={results:[],meta:{}};return r(t)&&e&&r(e.resultDelimiter)?i=s._parseResults.call(this,e,n,i):i.error=new Error("Text schema parse failure"),i},_parseResults:function(t,n,s){var o=t.resultDelimiter,u=r(t.fieldDelimiter)&&t.fieldDelimiter,a=t.resultFields||[],f=[],l=e.DataSchema.Base.parse,c,h,p,d,v,m,g,y,b;n.slice(-o.length)===o&&(n=n.slice(0,-o.length)),c=n.split(t.resultDelimiter);if(u)for(y=c.length-1;y>=0;--y){p={},d=c[y],h=d.split(t.fieldDelimiter);for(b=a.length-1;b>=0;--b)v=a[b],m=i(v.key)?v:v.key,g=i(h[m])?h[b]:h[m],p[m]=l.call(this,g,v);f[y]=p}else f=c;return s.results=f,s}};e.DataSchema.Text=e.mix(s,e.DataSchema.Base)},"3.7.3",{requires:["dataschema-base"]});
diff --git a/js/yui3/dataschema-xml/dataschema-xml-min.js b/js/yui3/dataschema-xml/dataschema-xml-min.js
new file mode 100644
index 000000000..3ea49837e
--- /dev/null
+++ b/js/yui3/dataschema-xml/dataschema-xml-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dataschema-xml",function(e,t){var n=e.Lang,r={1:!0,9:!0,11:!0},i;i={apply:function(e,t){var n=t,s={results:[],meta:{}};return n&&r[n.nodeType]&&e?(s=i._parseResults(e,n,s),s=i._parseMeta(e.metaFields,n,s)):s.error=new Error("XML schema parse failure"),s},_getLocationValue:function(t,n){var r=t.locator||t.key||t,s=n.ownerDocument||n,o,u,a=null;try{o=i._getXPathResult(r,n,s);while(u=o.iterateNext())a=u.textContent||u.value||u.text||u.innerHTML||u.innerText||null;return e.DataSchema.Base.parse.call(this,a,t)}catch(f){}return null},_getXPathResult:function(t,r,i){if(!n.isUndefined(i.evaluate))return i.evaluate(t,r,i.createNSResolver(r.ownerDocument?r.ownerDocument.documentElement:r.documentElement),0,null);var s=[],o=t.split(/\b\/\b/),u=0,a=o.length,f,l,c,h;try{try{i.setProperty("SelectionLanguage","XPath")}catch(p){}s=r.selectNodes(t)}catch(p){for(;u<a&&r;u++){f=o[u];if(f.indexOf("[")>-1&&f.indexOf("]")>-1)l=f.slice(f.indexOf("[")+1,f.indexOf("]")),l--,r=r.children[l],h=!0;else if(f.indexOf("@")>-1)l=f.substr(f.indexOf("@")),r=l?r.getAttribute(l.replace("@","")):r;else if(-1<f.indexOf("//"))l=r.getElementsByTagName(f.substr(2)),r=l.length?l[l.length-1]:null;else if(a!=u+1)for(c=r.childNodes.length-1;0<=c;c-=1)f===r.childNodes[c].tagName&&(r=r.childNodes[c],c=-1)}r&&(n.isString(r)?s[0]={value:r}:h?s[0]={value:r.innerHTML}:s=e.Array(r.childNodes,0,!0))}return{index:0,iterateNext:function(){if(this.index>=this.values.length)return undefined;var e=this.values[this.index];return this.index+=1,e},values:s}},_parseField:function(e,t,n){var r=e.key||e,s;e.schema?(s={results:[],meta:{}},s=i._parseResults(e.schema,n,s),t[r]=s.results):t[r]=i._getLocationValue(e,n)},_parseMeta:function(e,t,r){if(n.isObject(e)){var s,o=t.ownerDocument||t;for(s in e)e.hasOwnProperty(s)&&(r.meta[s]=i._getLocationValue(e[s],o))}return r},_parseResult:function(e,t){var n={},r;for(r=e.length-1;0<=r;r--)i._parseField(e[r],n,t);return n},_parseResults:function(e,t,r){if(e.resultListLocator&&n.isArray(e.resultFields)){var s=t.ownerDocument||t,o=e.resultFields,u=[],a,f,l=0;if(e.resultListLocator.match(/^[:\-\w]+$/)){f=t.getElementsByTagName(e.resultListLocator);for(l=f.length-1;l>=0;--l)u[l]=i._parseResult(o,f[l])}else{f=i._getXPathResult(e.resultListLocator,t,s);while(a=f.iterateNext())u[l]=i._parseResult(o,a),l+=1}u.length?r.results=u:r.error=new Error("XML schema result nodes retrieval failure")}return r}},e.DataSchema.XML=e.mix(i,e.DataSchema.Base)},"3.7.3",{requires:["dataschema-base"]});
diff --git a/js/yui3/datasource-arrayschema/datasource-arrayschema-min.js b/js/yui3/datasource-arrayschema/datasource-arrayschema-min.js
new file mode 100644
index 000000000..4a3f2a83c
--- /dev/null
+++ b/js/yui3/datasource-arrayschema/datasource-arrayschema-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-arrayschema",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.mix(n,{NS:"schema",NAME:"dataSourceArraySchema",ATTRS:{schema:{}}}),e.extend(n,e.Plugin.Base,{initializer:function(e){this.doBefore("_defDataFn",this._beforeDefDataFn)},_beforeDefDataFn:function(t){var n=e.DataSource.IO&&this.get("host")instanceof e.DataSource.IO&&e.Lang.isString(t.data.responseText)?t.data.responseText:t.data,r=e.DataSchema.Array.apply.call(this,this.get("schema"),n),i=t.details[0];return r||(r={meta:{},results:n}),i.response=r,this.get("host").fire("response",i),new e.Do.Halt("DataSourceArraySchema plugin halted _defDataFn")}}),e.namespace("Plugin").DataSourceArraySchema=n},"3.7.3",{requires:["datasource-local","plugin","dataschema-array"]});
diff --git a/js/yui3/datasource-cache/datasource-cache-min.js b/js/yui3/datasource-cache/datasource-cache-min.js
new file mode 100644
index 000000000..123f060c7
--- /dev/null
+++ b/js/yui3/datasource-cache/datasource-cache-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-cache",function(e,t){function r(t){var n=t&&t.cache?t.cache:e.Cache,r=e.Base.create("dataSourceCache",n,[e.Plugin.Base,e.Plugin.DataSourceCacheExtension]),i=new r(t);return r.NS="tmpClass",i}var n=function(){};e.mix(n,{NS:"cache",NAME:"dataSourceCacheExtension"}),n.prototype={initializer:function(e){this.doBefore("_defRequestFn",this._beforeDefRequestFn),this.doBefore("_defResponseFn",this._beforeDefResponseFn)},_beforeDefRequestFn:function(t){var n=this.retrieve(t.request)||null,r=t.details[0];if(n&&n.response)return r.cached=n.cached,r.response=n.response,r.data=n.data,this.get("host").fire("response",r),new e.Do.Halt("DataSourceCache extension halted _defRequestFn")},_beforeDefResponseFn:function(e){e.response&&!e.cached&&this.add(e.request,e.response)}},e.namespace("Plugin").DataSourceCacheExtension=n,e.mix(r,{NS:"cache",NAME:"dataSourceCache"}),e.namespace("Plugin").DataSourceCache=r},"3.7.3",{requires:["datasource-local","plugin","cache-base"]});
diff --git a/js/yui3/datasource-function/datasource-function-min.js b/js/yui3/datasource-function/datasource-function-min.js
new file mode 100644
index 000000000..cc0f218e9
--- /dev/null
+++ b/js/yui3/datasource-function/datasource-function-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-function",function(e,t){var n=e.Lang,r=function(){r.superclass.constructor.apply(this,arguments)};e.mix(r,{NAME:"dataSourceFunction",ATTRS:{source:{validator:n.isFunction}}}),e.extend(r,e.DataSource.Local,{_defRequestFn:function(e){var t=this.get("source"),n=e.details[0];if(t)try{n.data=t(e.request,this,e)}catch(r){n.error=r}else n.error=new Error("Function data failure");return this.fire("data",n),e.tId}}),e.DataSource.Function=r},"3.7.3",{requires:["datasource-local"]});
diff --git a/js/yui3/datasource-get/datasource-get-min.js b/js/yui3/datasource-get/datasource-get-min.js
new file mode 100644
index 000000000..91a8eae92
--- /dev/null
+++ b/js/yui3/datasource-get/datasource-get-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-get",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.DataSource.Get=e.extend(n,e.DataSource.Local,{_defRequestFn:function(t){var n=this.get("source"),r=this.get("get"),i=e.guid().replace(/\-/g,"_"),s=this.get("generateRequestCallback"),o=t.details[0],u=this;return this._last=i,YUI.Env.DataSource.callbacks[i]=function(n){delete YUI.Env.DataSource.callbacks[i],delete e.DataSource.Local.transactions[t.tId];var r=u.get("asyncMode")!=="ignoreStaleResponses"||u._last===i;r&&(o.data=n,u.fire("data",o))},n+=t.request+s.call(this,i),e.DataSource.Local.transactions[t.tId]=r.script(n,{autopurge:!0,onFailure:function(n){delete YUI.Env.DataSource.callbacks[i],delete e.DataSource.Local.transactions[t.tId],o.error=new Error(n.msg||"Script node data failure"),u.fire("data",o)},onTimeout:function(n){delete YUI.Env.DataSource.callbacks[i],delete e.DataSource.Local.transactions[t.tId],o.error=new Error(n.msg||"Script node data timeout"),u.fire("data",o)}}),t.tId},_generateRequest:function(e){return"&"+this.get("scriptCallbackParam")+"=YUI.Env.DataSource.callbacks."+e}},{NAME:"dataSourceGet",ATTRS:{get:{value:e.Get,cloneDefaultValue:!1},asyncMode:{value:"allowAll"},scriptCallbackParam:{value:"callback"},generateRequestCallback:{value:function(){return this._generateRequest.apply(this,arguments)}}}}),YUI.namespace("Env.DataSource.callbacks")},"3.7.3",{requires:["datasource-local","get"]});
diff --git a/js/yui3/datasource-io/datasource-io-min.js b/js/yui3/datasource-io/datasource-io-min.js
new file mode 100644
index 000000000..9e14c4f7c
--- /dev/null
+++ b/js/yui3/datasource-io/datasource-io-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-io",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.mix(n,{NAME:"dataSourceIO",ATTRS:{io:{value:e.io,cloneDefaultValue:!1},ioConfig:{value:null}}}),e.extend(n,e.DataSource.Local,{initializer:function(e){this._queue={interval:null,conn:null,requests:[]}},successHandler:function(t,n,r){var i=this.get("ioConfig"),s=r.details[0];delete e.DataSource.Local.transactions[r.tId],s.data=n,this.fire("data",s),i&&i.on&&i.on.success&&i.on.success.apply(i.context||e,arguments)},failureHandler:function(t,n,r){var i=this.get("ioConfig"),s=r.details[0];delete e.DataSource.Local.transactions[r.tId],s.error=new Error("IO data failure"),s.data=n,this.fire("data",s),i&&i.on&&i.on.failure&&i.on.failure.apply(i.context||e,arguments)},_queue:null,_defRequestFn:function(t){var n=this.get("source"),r=this.get("io"),i=this.get("ioConfig"),s=t.request,o=e.merge(i,t.cfg,{on:e.merge(i,{success:this.successHandler,failure:this.failureHandler}),context:this,arguments:t});return e.Lang.isString(s)&&(o.method&&o.method.toUpperCase()==="POST"?o.data=o.data?o.data+s:s:n+=s),e.DataSource.Local.transactions[t.tId]=r(n,o),t.tId}}),e.DataSource.IO=n},"3.7.3",{requires:["datasource-local","io-base"]});
diff --git a/js/yui3/datasource-jsonschema/datasource-jsonschema-min.js b/js/yui3/datasource-jsonschema/datasource-jsonschema-min.js
new file mode 100644
index 000000000..4fc27494e
--- /dev/null
+++ b/js/yui3/datasource-jsonschema/datasource-jsonschema-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-jsonschema",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.mix(n,{NS:"schema",NAME:"dataSourceJSONSchema",ATTRS:{schema:{}}}),e.extend(n,e.Plugin.Base,{initializer:function(e){this.doBefore("_defDataFn",this._beforeDefDataFn)},_beforeDefDataFn:function(t){var n=t.data&&(t.data.responseText||t.data),r=this.get("schema"),i=t.details[0];return i.response=e.DataSchema.JSON.apply.call(this,r,n)||{meta:{},results:n},this.get("host").fire("response",i),new e.Do.Halt("DataSourceJSONSchema plugin halted _defDataFn")}}),e.namespace("Plugin").DataSourceJSONSchema=n},"3.7.3",{requires:["datasource-local","plugin","dataschema-json"]});
diff --git a/js/yui3/datasource-local/datasource-local-min.js b/js/yui3/datasource-local/datasource-local-min.js
new file mode 100644
index 000000000..1eab931c9
--- /dev/null
+++ b/js/yui3/datasource-local/datasource-local-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-local",function(e,t){var n=e.Lang,r=function(){r.superclass.constructor.apply(this,arguments)};e.mix(r,{NAME:"dataSourceLocal",ATTRS:{source:{value:null}},_tId:0,transactions:{},issueCallback:function(e,t){var n=e.on||e.callback,r=n&&n.success,i=e.details[0];i.error=e.error||e.response.error,i.error&&(t.fire("error",i),r=n&&n.failure),r&&r(i)}}),e.extend(r,e.Base,{initializer:function(e){this._initEvents()},_initEvents:function(){this.publish("request",{defaultFn:e.bind("_defRequestFn",this),queuable:!0}),this.publish("data",{defaultFn:e.bind("_defDataFn",this),queuable:!0}),this.publish("response",{defaultFn:e.bind("_defResponseFn",this),queuable:!0})},_defRequestFn:function(e){var t=this.get("source"),r=e.details[0];n.isUndefined(t)&&(r.error=new Error("Local source undefined")),r.data=t,this.fire("data",r)},_defDataFn:function(e){var t=e.data,r=e.meta,i={results:n.isArray(t)?t:[t],meta:r?r:{}},s=e.details[0];s.response=i,this.fire("response",s)},_defResponseFn:function(e){r.issueCallback(e,this)},sendRequest:function(e){var t=r._tId++,n;return e=e||{},n=e.on||e.callback,this.fire("request",{tId:t,request:e.request,on:n,callback:n,cfg:e.cfg||{}}),t}}),e.namespace("DataSource").Local=r},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/datasource-polling/datasource-polling-min.js b/js/yui3/datasource-polling/datasource-polling-min.js
new file mode 100644
index 000000000..035b65f0b
--- /dev/null
+++ b/js/yui3/datasource-polling/datasource-polling-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-polling",function(e,t){function n(){this._intervals={}}n.prototype={_intervals:null,setInterval:function(t,n){var r=e.later(t,this,this.sendRequest,[n],!0);return this._intervals[r.id]=r,e.later(0,this,this.sendRequest,[n]),r.id},clearInterval:function(e,t){e=t||e,this._intervals[e]&&(this._intervals[e].cancel(),delete this._intervals[e])},clearAllIntervals:function(){e.each(this._intervals,this.clearInterval,this)}},e.augment(e.DataSource.Local,n)},"3.7.3",{requires:["datasource-local"]});
diff --git a/js/yui3/datasource-textschema/datasource-textschema-min.js b/js/yui3/datasource-textschema/datasource-textschema-min.js
new file mode 100644
index 000000000..9ca0c303c
--- /dev/null
+++ b/js/yui3/datasource-textschema/datasource-textschema-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-textschema",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.mix(n,{NS:"schema",NAME:"dataSourceTextSchema",ATTRS:{schema:{}}}),e.extend(n,e.Plugin.Base,{initializer:function(e){this.doBefore("_defDataFn",this._beforeDefDataFn)},_beforeDefDataFn:function(t){var n=this.get("schema"),r=t.details[0],i=t.data.responseText||t.data;return r.response=e.DataSchema.Text.apply.call(this,n,i)||{meta:{},results:i},this.get("host").fire("response",r),new e.Do.Halt("DataSourceTextSchema plugin halted _defDataFn")}}),e.namespace("Plugin").DataSourceTextSchema=n},"3.7.3",{requires:["datasource-local","plugin","dataschema-text"]});
diff --git a/js/yui3/datasource-xmlschema/datasource-xmlschema-min.js b/js/yui3/datasource-xmlschema/datasource-xmlschema-min.js
new file mode 100644
index 000000000..2a11b5df0
--- /dev/null
+++ b/js/yui3/datasource-xmlschema/datasource-xmlschema-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datasource-xmlschema",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.mix(n,{NS:"schema",NAME:"dataSourceXMLSchema",ATTRS:{schema:{}}}),e.extend(n,e.Plugin.Base,{initializer:function(e){this.doBefore("_defDataFn",this._beforeDefDataFn)},_beforeDefDataFn:function(t){var n=this.get("schema"),r=t.details[0],i=e.XML.parse(t.data.responseText)||t.data;return r.response=e.DataSchema.XML.apply.call(this,n,i)||{meta:{},results:i},this.get("host").fire("response",r),new e.Do.Halt("DataSourceXMLSchema plugin halted _defDataFn")}}),e.namespace("Plugin").DataSourceXMLSchema=n},"3.7.3",{requires:["datasource-local","plugin","datatype-xml","dataschema-xml"]});
diff --git a/js/yui3/datatable-base-deprecated/assets/datatable-base-deprecated-core.css b/js/yui3/datatable-base-deprecated/assets/datatable-base-deprecated-core.css
new file mode 100644
index 000000000..ac271f052
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/assets/datatable-base-deprecated-core.css
@@ -0,0 +1,93 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* foundational CSS */
+
+/* mask */
+.yui3-skin-sam .yui3-datatable-mask {
+ position:absolute;
+ z-index:9500;
+}
+
+/* scrollable */
+.yui3-datatable-tmp {
+ position:absolute;
+ left:-9000px;
+}
+
+.yui3-datatable-scrollable .yui3-datatable-bd {
+ overflow:auto;
+}
+.yui3-datatable-scrollable .yui3-datatable-hd {
+ overflow:hidden;
+ position:relative; /* for ie overflow bug http://rowanw.com/bugs/overflow_relative.htm */
+}
+
+.yui3-datatable-scrollable .yui3-datatable-bd thead tr,
+.yui3-datatable-scrollable .yui3-datatable-bd thead th {
+ position:absolute;
+ left:-1500px;
+}
+
+.yui3-datatable-scrollable tbody {
+ -moz-outline:none;
+}
+
+/* sortable columns */
+
+.yui3-skin-sam thead .yui3-datatable-sortable {
+ cursor:pointer;
+}
+
+/* draggable columns */
+.yui3-skin-sam thead .yui3-datatable-draggable {
+ cursor: move;
+}
+.yui3-datatable-coltarget {
+ position: absolute;
+ z-index: 999;
+}
+
+/* resizeable columns */
+.yui3-datatable-hd {
+ zoom:1;
+}
+th.yui3-datatable-resizeable .yui3-datatable-resizerliner {
+ position:relative;
+}
+.yui3-datatable-resizer {
+ position:absolute;
+ right:0;
+ bottom:0;
+ height:100%;
+ cursor:e-resize;
+ cursor:col-resize;
+ background-color:#CCC;opacity:0;filter: alpha(opacity=0); /* Bug 1952811: IE transparency z-index */
+}
+.yui3-datatable-resizerproxy {
+ visibility:hidden;
+ position:absolute;
+ z-index:9000;
+ background-color:#CCC;opacity:0;filter: alpha(opacity=0); /* Bug 1952811: IE transparency z-index */
+}
+
+/* hidden columns */
+th.yui3-datatable-hidden .yui3-datatable-liner,
+td.yui3-datatable-hidden .yui3-datatable-liner,
+th.yui3-datatable-hidden .yui3-datatable-resizer {
+ /*TODO: document change from 2.5.2 to 2.6
+ margin:0;
+ padding:0;
+ white-space:nowrap;
+ width:1px;
+ overflow:hidden;*/
+ display:none;
+}
+
+/* editing */
+.yui3-datatable-editor, .yui3-datatable-editor-shim {
+ position:absolute;z-index:9000;
+}
diff --git a/js/yui3/datatable-base-deprecated/assets/skins/night/datatable-base-deprecated.css b/js/yui3/datatable-base-deprecated/assets/skins/night/datatable-base-deprecated.css
new file mode 100644
index 000000000..a4724a78d
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/assets/skins/night/datatable-base-deprecated.css
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-datatable-mask{position:absolute;z-index:9500}.yui3-datatable-tmp{position:absolute;left:-9000px}.yui3-datatable-scrollable .yui3-datatable-bd{overflow:auto}.yui3-datatable-scrollable .yui3-datatable-hd{overflow:hidden;position:relative}.yui3-datatable-scrollable .yui3-datatable-bd thead tr,.yui3-datatable-scrollable .yui3-datatable-bd thead th{position:absolute;left:-1500px}.yui3-datatable-scrollable tbody{-moz-outline:0}.yui3-skin-sam thead .yui3-datatable-sortable{cursor:pointer}.yui3-skin-sam thead .yui3-datatable-draggable{cursor:move}.yui3-datatable-coltarget{position:absolute;z-index:999}.yui3-datatable-hd{zoom:1}th.yui3-datatable-resizeable .yui3-datatable-resizerliner{position:relative}.yui3-datatable-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui3-datatable-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui3-datatable-hidden .yui3-datatable-liner,td.yui3-datatable-hidden .yui3-datatable-liner,th.yui3-datatable-hidden .yui3-datatable-resizer{display:none}.yui3-datatable-editor,.yui3-datatable-editor-shim{position:absolute;z-index:9000}.yui3-skin-night .yui3-datatable{font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:#8e8e8e}.yui3-skin-night .yui3-datatable table{margin:0;padding:0;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #323434;border-right:0}.yui3-skin-night .yui3-datatable thead{border-spacing:0}.yui3-skin-night .yui3-datatable caption{color:#474747;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui3-skin-night .yui3-datatable th{background-color:#3b3c3d;background:-moz-linear-gradient(0% 100% 90deg,#242526 0,#3b3c3d 96%,#2c2d2f 100%);background:-webkit-gradient(linear,left bottom,left top,from(#242526),color-stop(0.96,#3b3c3d),to(#2c2d2f))}.yui3-skin-night .yui3-datatable th,.yui3-skin-night .yui3-datatable th a{font-weight:normal;text-decoration:none;color:#eee;vertical-align:bottom}.yui3-skin-night .yui3-datatable th{margin:0;padding:0;border:0;border-right:1px solid #303030}.yui3-skin-night .yui3-datatable tr.yui3-datatable-first td{border-top:1px solid #323434}.yui3-skin-night .yui3-datatable th .yui3-datatable-liner{white-space:nowrap}.yui3-skin-night .yui3-datatable-liner{margin:0;padding:0;padding:4px 10px 4px 10px;overflow:visible;border:0 solid black}.yui3-skin-night .yui3-datatable-coltarget{width:5px;background-color:red}.yui3-skin-night .yui3-datatable td{margin:0;padding:0;border:0;border-right:1px solid #303030;text-align:left}.yui3-skin-night .yui3-datatable-list td{border-right:0}.yui3-skin-night .yui3-datatable-resizer{width:6px}.yui3-skin-night .yui3-datatable-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui3-skin-night .yui3-datatable-message{background-color:#FFF}.yui3-skin-night .yui3-datatable-scrollable thead .yui3-datatable-first th:last-child div{border-right:solid 30px #2f3031}.yui3-skin-night .yui3-datatable-scrollable table{border:0}.yui3-skin-night .yui3-datatable-scrollable .yui3-datatable-hd{border-left:1px solid #303030;border-top:1px solid #303030;border-right:1px solid #303030}.yui3-skin-night .yui3-datatable-scrollable .yui3-datatable-bd{border-left:1px solid #303030;border-bottom:1px solid #303030;border-right:1px solid #303030;background-color:#000}.yui3-skin-night .yui3-datatable-scrollable .yui3-datatable-data tr.yui3-datatable-last td{border-bottom:1px solid #303030}.yui3-skin-night th.yui3-datatable-asc,.yui3-skin-night th.yui3-datatable-desc{background-color:#555658;background:-moz-linear-gradient(0% 100% 90deg,#343536 0,#555658 96%,#3e3f41 100%);background:-webkit-gradient(linear,left bottom,left top,from(#343536),color-stop(0.96,#555658),to(#3e3f41))}.yui3-skin-night th.yui3-datatable-sortable .yui3-datatable-liner{padding-right:20px}.yui3-skin-night th.yui3-datatable-asc .yui3-datatable-liner{background:url(dt-arrow-up.png) no-repeat right}.yui3-skin-night th.yui3-datatable-desc .yui3-datatable-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui3-datatable-editable{cursor:pointer}.yui3-datatable-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui3-datatable-editor label{padding-left:4px;padding-right:6px}.yui3-datatable-editor .yui3-datatable-button{padding-top:6px;text-align:right}.yui3-datatable-editor .yui3-datatable-button button{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui3-datatable-editor .yui3-datatable-button button.yui3-datatable-default{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui3-datatable-editor .yui3-datatable-button button:hover{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1300px;color:#000}.yui3-datatable-editor .yui3-datatable-button button:active{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1700px;color:#000}.yui3-skin-night .yui3-datatable td{background-color:transparent}.yui3-skin-night tr.yui3-datatable-even td{background-color:#0e0e0e}.yui3-skin-night tr.yui3-datatable-odd td{background-color:#1d1e1e}.yui3-skin-night tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-night tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#191a1a}.yui3-skin-night tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-night tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#2b2c2c}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-even{background-color:#0e0e0e}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-odd{background-color:#0e0e0e}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#151515}
+.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#151515}.yui3-skin-night th.yui3-datatable-highlighted,.yui3-skin-night th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-night tr.yui3-datatable-highlighted,.yui3-skin-night tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-night tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-night tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-night tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}.yui3-skin-night .yui3-datatable-list th.yui3-datatable-highlighted,.yui3-skin-night .yui3-datatable-list th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-highlighted,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}.yui3-skin-night th.yui3-datatable-selected,.yui3-skin-night th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-night tr.yui3-datatable-selected td,.yui3-skin-night tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-night tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-night tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-night tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-night .yui3-datatable-list th.yui3-datatable-selected,.yui3-skin-night .yui3-datatable-list th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-selected td,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-night .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-night .yui3-datatable-paginator{display:block;margin:6px 0;white-space:nowrap}.yui3-skin-night .yui3-datatable-paginator .yui3-datatable-first,.yui3-skin-night .yui3-datatable-paginator .yui3-datatable-last,.yui3-skin-night .yui3-datatable-paginator .yui3-datatable-selected{padding:2px 6px}.yui3-skin-night .yui3-datatable-paginator a.yui3-datatable-first,.yui3-skin-night .yui3-datatable-paginator a.yui3-datatable-last{text-decoration:none}.yui3-skin-night .yui3-datatable-paginator .yui3-datatable-previous,.yui3-skin-night .yui3-datatable-paginator .yui3-datatable-next{display:none}.yui3-skin-night a.yui3-datatable-page{border:1px solid #303030;padding:2px 6px;text-decoration:none;background-color:#fff}.yui3-skin-night .yui3-datatable-selected{border:1px solid #fff;background-color:#fff}#yui3-css-stamp.skin-night-datatable-base-deprecated{display:none}
diff --git a/js/yui3/datatable-base-deprecated/assets/skins/sam/datatable-base-deprecated.css b/js/yui3/datatable-base-deprecated/assets/skins/sam/datatable-base-deprecated.css
new file mode 100644
index 000000000..412b71762
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/assets/skins/sam/datatable-base-deprecated.css
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-datatable-mask{position:absolute;z-index:9500}.yui3-datatable-tmp{position:absolute;left:-9000px}.yui3-datatable-scrollable .yui3-datatable-bd{overflow:auto}.yui3-datatable-scrollable .yui3-datatable-hd{overflow:hidden;position:relative}.yui3-datatable-scrollable .yui3-datatable-bd thead tr,.yui3-datatable-scrollable .yui3-datatable-bd thead th{position:absolute;left:-1500px}.yui3-datatable-scrollable tbody{-moz-outline:0}.yui3-skin-sam thead .yui3-datatable-sortable{cursor:pointer}.yui3-skin-sam thead .yui3-datatable-draggable{cursor:move}.yui3-datatable-coltarget{position:absolute;z-index:999}.yui3-datatable-hd{zoom:1}th.yui3-datatable-resizeable .yui3-datatable-resizerliner{position:relative}.yui3-datatable-resizer{position:absolute;right:0;bottom:0;height:100%;cursor:e-resize;cursor:col-resize;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}.yui3-datatable-resizerproxy{visibility:hidden;position:absolute;z-index:9000;background-color:#CCC;opacity:0;filter:alpha(opacity=0)}th.yui3-datatable-hidden .yui3-datatable-liner,td.yui3-datatable-hidden .yui3-datatable-liner,th.yui3-datatable-hidden .yui3-datatable-resizer{display:none}.yui3-datatable-editor,.yui3-datatable-editor-shim{position:absolute;z-index:9000}.yui3-skin-sam .yui3-datatable table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:separate;*border-collapse:collapse;border-spacing:0;border:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable thead{border-spacing:0}.yui3-skin-sam .yui3-datatable caption{color:#000;font-size:85%;font-weight:normal;font-style:italic;line-height:1;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable th{background:#d8d8da url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-datatable th,.yui3-skin-sam .yui3-datatable th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom}.yui3-skin-sam .yui3-datatable th{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable tr.yui3-datatable-first td{border-top:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable th .yui3-datatable-liner{white-space:nowrap}.yui3-skin-sam .yui3-datatable-liner{margin:0;padding:0;padding:4px 10px 4px 10px;overflow:visible;border:0 solid black}.yui3-skin-sam .yui3-datatable-coltarget{width:5px;background-color:red}.yui3-skin-sam .yui3-datatable td{margin:0;padding:0;border:0;border-right:1px solid #cbcbcb;text-align:left}.yui3-skin-sam .yui3-datatable-list td{border-right:0}.yui3-skin-sam .yui3-datatable-resizer{width:6px}.yui3-skin-sam .yui3-datatable-mask{background-color:#000;opacity:.25;filter:alpha(opacity=25)}.yui3-skin-sam .yui3-datatable-message{background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable table{border:0}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-hd{border-left:1px solid #7f7f7f;border-top:1px solid #7f7f7f;border-right:1px solid #7f7f7f}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-bd{border-left:1px solid #7f7f7f;border-bottom:1px solid #7f7f7f;border-right:1px solid #7f7f7f;background-color:#FFF}.yui3-skin-sam .yui3-datatable-scrollable .yui3-datatable-data tr.yui3-datatable-last td{border-bottom:1px solid #7f7f7f}.yui3-skin-sam th.yui3-datatable-asc,.yui3-skin-sam th.yui3-datatable-desc{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -100px}.yui3-skin-sam th.yui3-datatable-sortable .yui3-datatable-liner{padding-right:20px}.yui3-skin-sam th.yui3-datatable-asc .yui3-datatable-liner{background:url(dt-arrow-up.png) no-repeat right}.yui3-skin-sam th.yui3-datatable-desc .yui3-datatable-liner{background:url(dt-arrow-dn.png) no-repeat right}tbody .yui3-datatable-editable{cursor:pointer}.yui3-datatable-editor{text-align:left;background-color:#f2f2f2;border:1px solid #808080;padding:6px}.yui3-datatable-editor label{padding-left:4px;padding-right:6px}.yui3-datatable-editor .yui3-datatable-button{padding-top:6px;text-align:right}.yui3-datatable-editor .yui3-datatable-button button{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px}.yui3-datatable-editor .yui3-datatable-button button.yui3-datatable-default{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1400px;background-color:#5584e0;border:1px solid #304369;color:#FFF}.yui3-datatable-editor .yui3-datatable-button button:hover{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1300px;color:#000}.yui3-datatable-editor .yui3-datatable-button button:active{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1700px;color:#000}.yui3-skin-sam .yui3-datatable td{background-color:transparent}.yui3-skin-sam tr.yui3-datatable-even td{background-color:#FFF}.yui3-skin-sam tr.yui3-datatable-odd td{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#dbeaff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd{background-color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-desc{background-color:#edf5ff}.yui3-skin-sam th.yui3-datatable-highlighted,.yui3-skin-sam th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam tr.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}
+.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-highlighted a{background-color:#b2d2ff}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-highlighted td.yui3-datatable-desc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-highlighted,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-highlighted{cursor:pointer;background-color:#b2d2ff}.yui3-skin-sam th.yui3-datatable-selected,.yui3-skin-sam th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam tr.yui3-datatable-selected td,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list th.yui3-datatable-selected a{background-color:#446cd7}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-asc,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-selected td.yui3-datatable-desc{background-color:#426fd9;color:#FFF}.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-even td.yui3-datatable-selected,.yui3-skin-sam .yui3-datatable-list tr.yui3-datatable-odd td.yui3-datatable-selected{background-color:#446cd7;color:#FFF}.yui3-skin-sam .yui3-datatable-paginator{display:block;margin:6px 0;white-space:nowrap}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-last,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-selected{padding:2px 6px}.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-first,.yui3-skin-sam .yui3-datatable-paginator a.yui3-datatable-last{text-decoration:none}.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-previous,.yui3-skin-sam .yui3-datatable-paginator .yui3-datatable-next{display:none}.yui3-skin-sam a.yui3-datatable-page{border:1px solid #cbcbcb;padding:2px 6px;text-decoration:none;background-color:#fff}.yui3-skin-sam .yui3-datatable-selected{border:1px solid #fff;background-color:#fff}#yui3-css-stamp.skin-sam-datatable-base-deprecated{display:none}
diff --git a/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-dn.png b/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-dn.png
new file mode 100644
index 000000000..9c42b8331
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-dn.png
Binary files differ
diff --git a/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-up.png b/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-up.png
new file mode 100644
index 000000000..07e237512
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/assets/skins/sam/dt-arrow-up.png
Binary files differ
diff --git a/js/yui3/datatable-base-deprecated/datatable-base-deprecated-min.js b/js/yui3/datatable-base-deprecated/datatable-base-deprecated-min.js
new file mode 100644
index 000000000..491944d5b
--- /dev/null
+++ b/js/yui3/datatable-base-deprecated/datatable-base-deprecated-min.js
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-base-deprecated",function(c){var w=c.Lang,g=w.isValue,F=c.Lang.sub,d=c.Node,t=d.create,p=c.ClassNameManager.getClassName,q="datatable",r="column",H="focus",K="keydown",h="mouseenter",o="mouseleave",k="mouseup",z="mousedown",C="click",v="dblclick",e=p(q,"columns"),B=p(q,"data"),b=p(q,"msg"),l=p(q,"liner"),E=p(q,"first"),i=p(q,"last"),u=p(q,"even"),A=p(q,"odd"),D="<table></table>",x="<col></col>",I='<thead class="'+e+'"></thead>',f='<tbody class="'+B+'"></tbody>',J='<th id="{id}" rowspan="{rowspan}" colspan="{colspan}" class="{classnames}" abbr="{abbr}"><div class="'+l+'">{value}</div></th>',G='<tr id="{id}"></tr>',a='<td headers="{headers}" class="{classnames}"><div class="'+l+'">{value}</div></td>',j="{value}",n='<tbody class="'+b+'"></tbody>';function m(L){m.superclass.constructor.apply(this,arguments);}c.mix(m,{NAME:"column",ATTRS:{id:{valueFn:"_defaultId",readOnly:true},key:{valueFn:"_defaultKey"},field:{valueFn:"_defaultField"},label:{valueFn:"_defaultLabel"},children:{value:null},abbr:{value:""},classnames:{readOnly:true,getter:"_getClassnames"},formatter:{},emptyCellValue:{value:"",validator:c.Lang.isString},sortable:{value:false},editor:{},width:{},resizeable:{},minimized:{},minWidth:{},maxAutoWidth:{}}});c.extend(m,c.Widget,{_defaultId:function(){return c.guid();},_defaultKey:function(){return c.guid();},_defaultField:function(){return this.get("key");},_defaultLabel:function(){return this.get("key");},_afterAbbrChange:function(L){this._uiSetAbbr(L.newVal);},keyIndex:null,headers:null,colSpan:1,rowSpan:1,parent:null,thNode:null,initializer:function(L){},destructor:function(){},_getClassnames:function(){return c.ClassNameManager.getClassName(r,this.get("key").replace(/[^\w\-]/g,""));},syncUI:function(){this._uiSetAbbr(this.get("abbr"));},_uiSetAbbr:function(L){this.thNode.set("abbr",L);}});c.Column=m;function y(L){y.superclass.constructor.apply(this,arguments);}c.mix(y,{NAME:"columnset",ATTRS:{definitions:{setter:"_setDefinitions"}}});c.extend(y,c.Base,{_setDefinitions:function(L){return c.clone(L);},tree:null,idHash:null,keyHash:null,keys:null,initializer:function(){var L=[],Q={},R={},P=[],O=this.get("definitions"),M=this;function N(Z,Y,X){var U=0,T=Y.length,W,V,S;Z++;if(!L[Z]){L[Z]=[];}for(;U<T;++U){W=Y[U];W=w.isString(W)?{key:W}:W;V=new c.Column(W);W.yuiColumnId=V.get("id");Q[V.get("id")]=V;R[V.get("key")]=V;if(X){V.parent=X;}if(w.isArray(W.children)){S=W.children;V._set("children",S);M._setColSpans(V,W);M._cascadePropertiesToChildren(V,S);if(!L[Z+1]){L[Z+1]=[];}N(Z,S,V);}else{V.keyIndex=P.length;P.push(V);}L[Z].push(V);}Z--;}N(-1,O);this.tree=L;this.idHash=Q;this.keyHash=R;this.keys=P;this._setRowSpans();this._setHeaders();},destructor:function(){},_cascadePropertiesToChildren:function(O,M){var N=0,L=M.length,P;for(;N<L;++N){P=M[N];if(O.get("className")&&(P.className===undefined)){P.className=O.get("className");}if(O.get("editor")&&(P.editor===undefined)){P.editor=O.get("editor");}if(O.get("formatter")&&(P.formatter===undefined)){P.formatter=O.get("formatter");}if(O.get("resizeable")&&(P.resizeable===undefined)){P.resizeable=O.get("resizeable");}if(O.get("sortable")&&(P.sortable===undefined)){P.sortable=O.get("sortable");}if(O.get("hidden")){P.hidden=true;}if(O.get("width")&&(P.width===undefined)){P.width=O.get("width");}if(O.get("minWidth")&&(P.minWidth===undefined)){P.minWidth=O.get("minWidth");}if(O.get("maxAutoWidth")&&(P.maxAutoWidth===undefined)){P.maxAutoWidth=O.get("maxAutoWidth");}}},_setColSpans:function(N,M){var O=0;function L(R){var S=R.children,Q=0,P=S.length;for(;Q<P;++Q){if(w.isArray(S[Q].children)){L(S[Q]);}else{O++;}}}L(M);N.colSpan=O;},_setRowSpans:function(){function L(N){var O=1,Q,P,M,S;function R(X,W){W=W||1;var V=0,T=X.length,U;for(;V<T;++V){U=X[V];if(w.isArray(U.children)){W++;R(U.children,W);W--;}else{if(U.get&&w.isArray(U.get("children"))){W++;R(U.get("children"),W);W--;}else{if(W>O){O=W;}}}}}for(M=0;M<N.length;M++){Q=N[M];R(Q);for(S=0;S<Q.length;S++){P=Q[S];if(!w.isArray(P.get("children"))){P.rowSpan=O;}}O=1;}}L(this.tree);},_setHeaders:function(){var Q,O,N=this.keys,M=0,L=N.length;function P(S,R){S.push(R.get("id"));if(R.parent){P(S,R.parent);}}for(;M<L;++M){Q=[];O=N[M];P(Q,O);O.headers=Q.reverse().join(" ");}},getColumn:function(){}});c.Columnset=y;function s(L){s.superclass.constructor.apply(this,arguments);}c.mix(s,{NAME:"dataTable",ATTRS:{columnset:{setter:"_setColumnset"},recordset:{valueFn:"_initRecordset",setter:"_setRecordset"},summary:{},caption:{},thValueTemplate:{value:j},tdValueTemplate:{value:j},trTemplate:{value:G}},HTML_PARSER:{}});c.extend(s,c.Widget,{thTemplate:J,tdTemplate:a,_theadNode:null,_tbodyNode:null,_msgNode:null,_setColumnset:function(L){return w.isArray(L)?new c.Columnset({definitions:L}):L;},_afterColumnsetChange:function(L){this._uiSetColumnset(L.newVal);},_setRecordset:function(L){if(w.isArray(L)){L=new c.Recordset({records:L});}L.addTarget(this);return L;},_afterRecordsetChange:function(L){this._uiSetRecordset(L.newVal);},_afterRecordsChange:function(L){this._uiSetRecordset(this.get("recordset"));},_afterSummaryChange:function(L){this._uiSetSummary(L.newVal);},_afterCaptionChange:function(L){this._uiSetCaption(L.newVal);},destructor:function(){this.get("recordset").removeTarget(this);},renderUI:function(){this._addTableNode(this.get("contentBox"));this._addColgroupNode(this._tableNode);this._addTheadNode(this._tableNode);this._addTbodyNode(this._tableNode);this._addMessageNode(this._tableNode);this._addCaptionNode(this._tableNode);},_addTableNode:function(L){if(!this._tableNode){this._tableNode=L.appendChild(t(D));}return this._tableNode;},_addColgroupNode:function(N){var L=this.get("columnset").keys.length,M=0,O=["<colgroup>"];for(;M<L;++M){O.push(x);}O.push("</colgroup>");this._colgroupNode=N.insertBefore(t(O.join("")),N.get("firstChild"));return this._colgroupNode;},_addTheadNode:function(L){if(L){this._theadNode=L.insertBefore(t(I),this._colgroupNode.next());return this._theadNode;}},_addTbodyNode:function(L){this._tbodyNode=L.appendChild(t(f));
+return this._tbodyNode;},_addMessageNode:function(L){this._msgNode=L.insertBefore(t(n),this._tbodyNode);return this._msgNode;},_addCaptionNode:function(L){this._captionNode=c.Node.create("<caption></caption>");},bindUI:function(){this.after({columnsetChange:this._afterColumnsetChange,summaryChange:this._afterSummaryChange,captionChange:this._afterCaptionChange,recordsetChange:this._afterRecordsChange,"recordset:tableChange":this._afterRecordsChange});},delegate:function(L){if(L==="dblclick"){this.get("boundingBox").delegate.apply(this.get("boundingBox"),arguments);}else{this.get("contentBox").delegate.apply(this.get("contentBox"),arguments);}},syncUI:function(){this._uiSetColumnset(this.get("columnset"));this._uiSetRecordset(this.get("recordset"));this._uiSetSummary(this.get("summary"));this._uiSetCaption(this.get("caption"));},_uiSetSummary:function(L){L=g(L)?L:"";this._tableNode.set("summary",L);},_uiSetCaption:function(N){var L=this._captionNode,M=L.inDoc(),O=N?(!M&&"prepend"):(M&&"removeChild");L.setContent(N||"");if(O){this._tableNode[O](L);}},_uiSetColumnset:function(P){var M=P.tree,R=this._theadNode,N=0,L=M.length,O=R.get("parentNode"),Q=R.next();R.remove();R.get("children").remove(true);for(;N<L;++N){this._addTheadTrNode({thead:R,columns:M[N],id:""},(N===0),(N===L-1));}O.insert(R,Q);},_addTheadTrNode:function(N,L,M){N.tr=this._createTheadTrNode(N,L,M);this._attachTheadTrNode(N);},_createTheadTrNode:function(S,M,R){var Q=t(F(this.get("trTemplate"),S)),O=0,N=S.columns,L=N.length,P;if(M){Q.addClass(E);}if(R){Q.addClass(i);}for(;O<L;++O){P=N[O];this._addTheadThNode({value:P.get("label"),column:P,tr:Q});}return Q;},_attachTheadTrNode:function(L){L.thead.appendChild(L.tr);},_addTheadThNode:function(L){L.th=this._createTheadThNode(L);this._attachTheadThNode(L);L.column.thNode=L.th;},_createTheadThNode:function(M){var L=M.column;M.id=L.get("id");M.colspan=L.colSpan;M.rowspan=L.rowSpan;M.abbr=L.get("abbr");M.classnames=L.get("classnames");M.value=F(this.get("thValueTemplate"),M);return t(F(this.thTemplate,M));},_attachTheadThNode:function(L){L.tr.appendChild(L.th);},_uiSetRecordset:function(O){var X=this,T=this._tbodyNode,W=T.get("parentNode"),P=T.next(),N=this.get("columnset").keys,R=this.get("tdValueTemplate"),L={},U,Q,S,M,V;T.remove();T=null;U=this._addTbodyNode(this._tableNode);U.remove();this._tbodyNode=U;L.tbody=U;L.rowTemplate=this.get("trTemplate");L.columns=[];for(Q=N.length-1;Q>=0;--Q){M=N[Q];L.columns[Q]={column:M,fields:M.get("field"),classnames:M.get("classnames"),emptyCellValue:M.get("emptyCellValue")};V=M.get("formatter");if(w.isFunction(V)){V=c.bind(this._functionFormatter,this,V);}else{if(!w.isString(V)){V=R;}V=c.bind(this._templateFormatter,this,V);}L.columns[Q].formatter=V;}for(Q=0,S=O.size();Q<S;++Q){L.record=O.item(Q);L.data=L.record.get("data");L.rowindex=Q;this._addTbodyTrNode(L);}W.insert(this._tbodyNode,P);},_functionFormatter:function(L,N){var M=L.call(this,N);return(M!==undefined)?M:N.emptyCellValue;},_templateFormatter:function(L,M){if(M.value===undefined){M.value=M.emptyCellValue;}return F(L,M);},_addTbodyTrNode:function(M){var L=M.tbody.one("#"+M.record.get("id"));M.tr=L||this._createTbodyTrNode(M);this._attachTbodyTrNode(M);},_createTbodyTrNode:function(P){var N=P.columns,M,L,O;P.tr=t(F(P.rowTemplate,{id:P.record.get("id")}));for(M=0,L=N.length;M<L;++M){O=N[M];P.column=O.column;P.field=O.fields;P.classnames=O.classnames;P.formatter=O.formatter;P.emptyCellValue=O.emptyCellValue;this._addTbodyTdNode(P);}return P.tr;},_attachTbodyTrNode:function(Q){var N=Q.tbody,P=Q.tr,M=Q.rowindex,O=N.get("children").item(M)||null,L=(M%2);if(L){P.replaceClass(u,A);}else{P.replaceClass(A,u);}N.insertBefore(P,O);},_addTbodyTdNode:function(L){L.td=this._createTbodyTdNode(L);this._attachTbodyTdNode(L);delete L.td;},createCell:function(L){return L&&(L.td||(L.td=t(F(this.tdTemplate,L))));},_createTbodyTdNode:function(L){L.headers=L.column.headers;L.value=this.formatDataCell(L);return L.td||this.createCell(L);},_attachTbodyTdNode:function(L){L.tr.appendChild(L.td);},formatDataCell:function(L){L.value=L.data[L.field];return L.formatter.call(this,L);},_initRecordset:function(){return new c.Recordset({records:[]});}});c.namespace("DataTable").Base=s;},"3.7.3",{requires:["recordset-base","widget","substitute","event-mouseenter"]}); \ No newline at end of file
diff --git a/js/yui3/datatable-base/assets/datatable-base-core.css b/js/yui3/datatable-base/assets/datatable-base-core.css
new file mode 100644
index 000000000..96955cbae
--- /dev/null
+++ b/js/yui3/datatable-base/assets/datatable-base-core.css
@@ -0,0 +1,10 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* foundational CSS */
+.yui3-datatable-table {
+ empty-cells: show;
+}
diff --git a/js/yui3/datatable-base/assets/skins/night/datatable-base.css b/js/yui3/datatable-base/assets/skins/night/datatable-base.css
new file mode 100644
index 000000000..1c4f62703
--- /dev/null
+++ b/js/yui3/datatable-base/assets/skins/night/datatable-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-table{empty-cells:show}.yui3-skin-night .yui3-datatable{color:#8e8e8e;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif}.yui3-skin-night .yui3-datatable-table{border:1px solid #323434;border-collapse:separate;border-spacing:0;color:#8e8e8e;margin:0;padding:0}.yui3-skin-night .yui3-datatable-caption{color:#474747;font:italic 85%/1 HelveticaNeue,arial,helvetica,clean,sans-serif;padding:1em 0;text-align:center}.yui3-skin-night .yui3-datatable-cell,.yui3-skin-night .yui3-datatable-header{border-left:1px solid #303030;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:4px 10px 4px 10px}.yui3-skin-night .yui3-datatable-cell:first-child,.yui3-skin-night .yui3-datatable-first-header{border-left-width:0}.yui3-skin-night .yui3-datatable-header{background-color:#3b3c3d;background:-moz-linear-gradient(0% 100% 90deg,#242526 0,#3b3c3d 96%,#2c2d2f 100%);background:-webkit-gradient(linear,left bottom,left top,from(#242526),color-stop(0.96,#3b3c3d),to(#2c2d2f));color:#eee;font-weight:normal;text-align:left;vertical-align:bottom;white-space:nowrap}.yui3-skin-night .yui3-datatable-cell{background-color:transparent}.yui3-skin-night .yui3-datatable-even .yui3-datatable-cell{background-color:#0e0e0e}.yui3-skin-night .yui3-datatable-odd .yui3-datatable-cell{background-color:#1d1e1e}#yui3-css-stamp.skin-night-datatable-base{display:none}
diff --git a/js/yui3/datatable-base/assets/skins/sam/datatable-base.css b/js/yui3/datatable-base/assets/skins/sam/datatable-base.css
new file mode 100644
index 000000000..fcb482585
--- /dev/null
+++ b/js/yui3/datatable-base/assets/skins/sam/datatable-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-table{empty-cells:show}.yui3-skin-sam .yui3-datatable-table{margin:0;padding:0;font-family:arial,sans-serif;border-collapse:separate;border-spacing:0;border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.yui3-skin-sam .yui3-datatable-cell,.yui3-skin-sam .yui3-datatable-header{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:4px 10px 4px 10px}.yui3-skin-sam .yui3-datatable-cell:first-child,.yui3-skin-sam .yui3-datatable-first-header{border-left-width:0}.yui3-skin-sam .yui3-datatable-header{background:#fff url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;background-image:-webkit-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-moz-linear-gradient(top,transparent 40%,rgba(0,0,0,0.21));background-image:-ms-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-o-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:linear-gradient(transparent 40%,rgba(0,0,0,0.21));color:#000;font-weight:normal;text-align:left;text-shadow:0 1px 1px #fff;vertical-align:bottom;white-space:nowrap}.yui3-skin-sam .yui3-datatable-cell{background-color:transparent}.yui3-skin-sam .yui3-datatable-even .yui3-datatable-cell{background-color:#fff}.yui3-skin-sam .yui3-datatable-odd .yui3-datatable-cell{background-color:#edf5ff}#yui3-css-stamp.skin-sam-datatable-base{display:none}
diff --git a/js/yui3/datatable-base/datatable-base-min.js b/js/yui3/datatable-base/datatable-base-min.js
new file mode 100644
index 000000000..b005bc56b
--- /dev/null
+++ b/js/yui3/datatable-base/datatable-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-base",function(e,t){e.DataTable.Base=e.Base.create("datatable",e.Widget,[e.DataTable.Core],{delegate:function(){var e=this.get("contentBox");return e.delegate.apply(e,arguments)},destructor:function(){this.view&&this.view.destroy()},getCell:function(e,t){return this.view&&this.view.getCell&&this.view.getCell.apply(this.view,arguments)},getRow:function(e){return this.view&&this.view.getRow&&this.view.getRow.apply(this.view,arguments)},_afterDisplayColumnsChange:function(e){this._extractDisplayColumns(e.newVal||[])},bindUI:function(){this._eventHandles.relayCoreChanges=this.after(["columnsChange","dataChange","summaryChange","captionChange","widthChange"],e.bind("_relayCoreAttrChange",this))},_defRenderViewFn:function(e){e.view.render()},_extractDisplayColumns:function(t){function r(t){var i,s,o;for(i=0,s=t.length;i<s;++i)o=t[i],e.Lang.isArray(o.children)?r(o.children):n.push(o)}var n=[];r(t),this._displayColumns=n},initializer:function(){this.publish("renderView",{defaultFn:e.bind("_defRenderViewFn",this)}),this._extractDisplayColumns(this.get("columns")||[]),this.after("columnsChange",e.bind("_afterDisplayColumnsChange",this))},_relayCoreAttrChange:function(e){var t=e.attrName==="data"?"modelList":e.attrName;this.view.set(t,e.newVal)},renderUI:function(){var t=this,n=this.get("view");n&&(this.view=new n(e.merge(this.getAttrs(),{host:this,container:this.get("contentBox"),modelList:this.data},this.get("viewConfig"))),this._eventHandles.legacyFeatureProps||(this._eventHandles.legacyFeatureProps=this.view.after({renderHeader:function(e){t.head=e.view,t._theadNode=e.view.theadNode,t._tableNode=e.view.get("container")},renderFooter:function(e){t.foot=e.view,t._tfootNode=e.view.tfootNode,t._tableNode=e.view.get("container")},renderBody:function(e){t.body=e.view,t._tbodyNode=e.view.tbodyNode,t._tableNode=e.view.get("container")},renderTable:function(e){var n=this.get("container");t._tableNode=this.tableNode||n.one("."+this.getClassName("table")+", table"),t._captionNode=this.captionNode||n.one("caption"),t._theadNode||(t._theadNode=n.one("."+this.getClassName("columns")+", thead")),t._tbodyNode||(t._tbodyNode=n.one("."+this.getClassName("data")+", tbody")),t._tfootNode||(t._tfootNode=n.one("."+this.getClassName("footer")+", tfoot"))}})),this.view.addTarget(this))},syncUI:function(){this.view&&this.fire("renderView",{view:this.view})},_validateView:function(t){return t===null||e.Lang.isFunction(t)&&t.prototype.render}},{ATTRS:{view:{value:e.DataTable.TableView,validator:"_validateView"},viewConfig:{}}}),e.DataTable=e.mix(e.Base.create("datatable",e.DataTable.Base,[]),e.DataTable)},"3.7.3",{requires:["datatable-core","datatable-table","datatable-head","datatable-body","base-build","widget"],skinnable:!0});
diff --git a/js/yui3/datatable-body/datatable-body-min.js b/js/yui3/datatable-body/datatable-body-min.js
new file mode 100644
index 000000000..8f9ee5266
--- /dev/null
+++ b/js/yui3/datatable-body/datatable-body-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-body",function(e,t){var n=e.Lang,r=n.isArray,i=n.isNumber,s=n.isString,o=n.sub,u=e.Escape.html,a=e.Array,f=e.bind,l=e.Object;e.namespace("DataTable").BodyView=e.Base.create("tableBody",e.View,[],{CELL_TEMPLATE:'<td {headers} class="{className}">{content}</td>',ROW_TEMPLATE:'<tr id="{rowId}" data-yui3-record="{clientId}" class="{rowClass}">{content}</tr>',TBODY_TEMPLATE:'<tbody class="{className}"></tbody>',getCell:function(t,n){var i=this.tbodyNode,o,u,a,f;if(t&&i){r(t)?(o=i.get("children").item(t[0]),u=o&&o.get("children").item(t[1])):e.instanceOf(t,e.Node)&&(u=t.ancestor("."+this.getClassName("cell"),!0));if(u&&n){f=i.get("firstChild.rowIndex");if(s(n))switch(n){case"above":n=[-1,0];break;case"below":n=[1,0];break;case"next":n=[0,1];break;case"previous":n=[0,-1]}r(n)&&(a=u.get("parentNode.rowIndex")+n[0]-f,o=i.get("children").item(a),a=u.get("cellIndex")+n[1],u=o&&o.get("children").item(a))}}return u||null},getClassName:function(){var t=this.host,n;return t&&t.getClassName?t.getClassName.apply(t,arguments):(n=a(arguments),n.unshift(this.constructor.NAME),e.ClassNameManager.getClassName.apply(e.ClassNameManager,n))},getRecord:function(t){var n=this.get("modelList"),r=this.tbodyNode,i=null,o;return r&&(s(t)&&(t=r.one("#"+t)),e.instanceOf(t,e.Node)&&(i=t.ancestor(function(e){return e.get("parentNode").compareTo(r)},!0),o=i&&n.getByClientId(i.getData("yui3-record")))),o||null},getRow:function(e){var t=this.tbodyNode,n=null;return t&&(e&&(e=this._idMap[e.get?e.get("clientId"):e]||e),n=i(e)?t.get("children").item(e):t.one("#"+e)),n},render:function(){var e=this.get("container"),t=this.get("modelList"),n=this.get("columns"),r=this.tbodyNode||(this.tbodyNode=this._createTBodyNode());return this._createRowTemplate(n),t&&(r.setHTML(this._createDataHTML(n)),this._applyNodeFormatters(r,n)),r.get("parentNode")!==e&&e.appendChild(r),this.bindUI(),this},_afterColumnsChange:function(e){this.render()},_afterDataChange:function(e){this.render()},_afterModelListChange:function(e){var t=this._eventHandles;t.dataChange&&(t.dataChange.detach(),delete t.dataChange,this.bindUI()),this.tbodyNode&&this.render()},_applyNodeFormatters:function(e,t){var n=this.host,r=this.get("modelList"),i=[],s="."+this.getClassName("liner"),o,u,a;for(u=0,a=t.length;u<a;++u)t[u].nodeFormatter&&i.push(u);r&&i.length&&(o=e.get("childNodes"),r.each(function(e,r){var u={data:e.toJSON(),record:e,rowIndex:r},a=o.item(r),f,l,c,h,p,d,v;if(a){p=a.get("childNodes");for(f=0,l=i.length;f<l;++f)d=p.item(i[f]),d&&(c=u.column=t[i[f]],h=c.key||c.id,u.value=e.get(h),u.td=d,u.cell=d.one(s)||d,v=c.nodeFormatter.call(n,u),v===!1&&d.destroy(!0))}}))},bindUI:function(){var e=this._eventHandles,t=this.get("modelList"),n=t.model.NAME+":change";e.columnsChange||(e.columnsChange=this.after("columnsChange",f("_afterColumnsChange",this))),t&&!e.dataChange&&(e.dataChange=t.after(["add","remove","reset",n],f("_afterDataChange",this)))},_createDataHTML:function(e){var t=this.get("modelList"),n="";return t&&t.each(function(t,r){n+=this._createRowHTML(t,r,e)},this),n},_createRowHTML:function(e,t,n){var r=e.toJSON(),i=e.get("clientId"),s={rowId:this._getRowId(i),clientId:i,rowClass:t%2?this.CLASS_ODD:this.CLASS_EVEN},a=this.host||this,f,l,c,h,p,d;for(f=0,l=n.length;f<l;++f){c=n[f],p=r[c.key],h=c._id||c.key,s[h+"-className"]="",c.formatter&&(d={value:p,data:r,column:c,record:e,className:"",rowClass:"",rowIndex:t},typeof c.formatter=="string"?p!==undefined&&(p=o(c.formatter,d)):(p=c.formatter.call(a,d),p===undefined&&(p=d.value),s[h+"-className"]=d.className,s.rowClass+=" "+d.rowClass));if(p===undefined||p===null||p==="")p=c.emptyCellValue||"";s[h]=c.allowHTML?p:u(p),s.rowClass=s.rowClass.replace(/\s+/g," ")}return o(this._rowTemplate,s)},_createRowTemplate:function(e){var t="",n=this.CELL_TEMPLATE,r,i,s,u,a,f,l;for(r=0,i=e.length;r<i;++r)s=e[r],u=s.key,a=s._id||u,f=(s._headers||[]).length>1?'headers="'+s._headers.join(" ")+'"':"",l={content:"{"+a+"}",headers:f,className:this.getClassName("col",a)+" "+(s.className||"")+" "+this.getClassName("cell")+" {"+a+"-className}"},s.nodeFormatter&&(l.content=""),t+=o(s.cellTemplate||n,l);this._rowTemplate=o(this.ROW_TEMPLATE,{content:t})},_createTBodyNode:function(){return e.Node.create(o(this.TBODY_TEMPLATE,{className:this.getClassName("data")}))},destructor:function(){(new e.EventHandle(l.values(this._eventHandles))).detach()},_getRowId:function(t){return this._idMap[t]||(this._idMap[t]=e.guid())},initializer:function(e){this.host=e.host,this._eventHandles={modelListChange:this.after("modelListChange",f("_afterModelListChange",this))},this._idMap={},this.CLASS_ODD=this.getClassName("odd"),this.CLASS_EVEN=this.getClassName("even")}})},"3.7.3",{requires:["datatable-core","view","classnamemanager"]});
diff --git a/js/yui3/datatable-column-widths/datatable-column-widths-min.js b/js/yui3/datatable-column-widths/datatable-column-widths-min.js
new file mode 100644
index 000000000..b46c88bbd
--- /dev/null
+++ b/js/yui3/datatable-column-widths/datatable-column-widths-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-column-widths",function(e,t){function i(){}var n=e.Lang.isNumber,r=e.Array.indexOf;e.Features.add("table","badColWidth",{test:function(){var t=e.one("body"),n,r;return t&&(n=t.insertBefore('<table style="position:absolute;visibility:hidden;border:0 none"><colgroup><col style="width:9px"></colgroup><tbody><tr><td style="padding:0 4px;font:normal 2px/2px arial;border:0 none">.</td></tr></tbody></table>',t.get("firstChild")),r=n.one("td").getComputedStyle("width")!=="1px",n.remove(!0)),r}}),e.mix(i.prototype,{COL_TEMPLATE:"<col/>",COLGROUP_TEMPLATE:"<colgroup/>",setColumnWidth:function(e,t){var i=this.getColumn(e),s=i&&r(this._displayColumns,i);return s>-1&&(n(t)&&(t+="px"),i.width=t,this._setColumnWidth(s,t)),this},_createColumnGroup:function(){return e.Node.create(this.COLGROUP_TEMPLATE)},initializer:function(e){this.after(["renderView","columnsChange"],this._uiSetColumnWidths)},_setColumnWidth:function(t,r){var i=this._colgroupNode,s=i&&i.all("col").item(t),o,u;s&&(r&&n(r)&&(r+="px"),s.setStyle("width",r),r&&e.Features.test("table","badColWidth")&&(o=this.getCell([0,t]),o&&(u=function(e){return parseInt(o.getComputedStyle(e),10)|0},s.setStyle("width",parseInt(r,10)-u("paddingLeft")-u("paddingRight")-u("borderLeftWidth")-u("borderRightWidth")+"px"))))},_uiSetColumnWidths:function(){if(!this.view)return;var e=this.COL_TEMPLATE,t=this._colgroupNode,n=this._displayColumns,r,i;t?t.empty():(t=this._colgroupNode=this._createColumnGroup(),this._tableNode.insertBefore(t,this._tableNode.one("> thead, > tfoot, > tbody")));for(r=0,i=n.length;r<i;++r)t.append(e),this._setColumnWidth(r,n[r].width)}},!0),e.DataTable.ColumnWidths=i,e.Base.mix(e.DataTable,[i])},"3.7.3",{requires:["datatable-base"]});
diff --git a/js/yui3/datatable-core/datatable-core-min.js b/js/yui3/datatable-core/datatable-core-min.js
new file mode 100644
index 000000000..61c1d7988
--- /dev/null
+++ b/js/yui3/datatable-core/datatable-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-core",function(e,t){var n=e.Attribute.INVALID_VALUE,r=e.Lang,i=r.isFunction,s=r.isObject,o=r.isArray,u=r.isString,a=r.isNumber,f=e.Array,l=e.Object.keys,c;c=e.namespace("DataTable").Core=function(){},c.ATTRS={columns:{validator:o,setter:"_setColumns",getter:"_getColumns"},recordType:{getter:"_getRecordType",setter:"_setRecordType"},data:{valueFn:"_initData",setter:"_setData",lazyAdd:!1},recordset:{setter:"_setRecordset",getter:"_getRecordset",lazyAdd:!1},columnset:{setter:"_setColumnset",getter:"_getColumnset",lazyAdd:!1}},e.mix(c.prototype,{getColumn:function(e){var t,n,r,i,u;s(e)&&!o(e)?t=e:t=this.get("columns."+e);if(t)return t;n=this.get("columns");if(a(e)||o(e)){e=f(e),u=n;for(r=0,i=e.length-1;u&&r<i;++r)u=u[e[r]]&&u[e[r]].children;return u&&u[e[r]]||null}return null},getRecord:function(e){var t=this.data.getById(e)||this.data.getByClientId(e);return t||(a(e)&&(t=this.data.item(e)),!t&&this.view&&this.view.getRecord&&(t=this.view.getRecord.apply(this.view,arguments))),t||null},_allowAdHocAttrs:!0,_afterColumnsChange:function(e){this._setColumnMap(e.newVal)},_afterDataChange:function(e){var t=e.newVal;this.data=e.newVal,!this.get("columns")&&t.size()&&this._initColumns()},_afterRecordTypeChange:function(e){var t=this.data.toJSON();this.data.model=e.newVal,this.data.reset(t),!this.get("columns")&&t&&(t.length?this._initColumns():this.set("columns",l(e.newVal.ATTRS)))},_createRecordClass:function(t){var n,r,i;if(o(t)){n={};for(r=0,i=t.length;r<i;++r)n[t[r]]={}}else s(t)&&(n=t);return e.Base.create("record",e.Model,[],null,{ATTRS:n})},destructor:function(){(new e.EventHandle(e.Object.values(this._eventHandles))).detach()},_getColumns:function(e,t){return t.length>8?this._columnMap:e},_getColumnset:function(e,t){return this.get(t.replace(/^columnset/,"columns"))},_getRecordType:function(e){return e||this.data&&this.data.model},_initColumns:function(){var e=this.get("columns")||[],t;!e.length&&this.data.size()&&(t=this.data.item(0),t.toJSON&&(t=t.toJSON()),this.set("columns",l(t))),this._setColumnMap(e)},_initCoreEvents:function(){this._eventHandles.coreAttrChanges=this.after({columnsChange:e.bind("_afterColumnsChange",this),recordTypeChange:e.bind("_afterRecordTypeChange",this),dataChange:e.bind("_afterDataChange",this)})},_initData:function(){var t=this.get("recordType"),n=new e.ModelList;return t&&(n.model=t),n},_initDataProperty:function(t){var n;this.data||(n=this.get("recordType"),t&&t.each&&t.toJSON?(this.data=t,n&&(this.data.model=n)):(this.data=new e.ModelList,n&&(this.data.model=n)),this.data.addTarget(this))},initializer:function(e){var t=e.data,n=e.columns,r;this._initDataProperty(t),n||(r=(e.recordType||e.data===this.data)&&this.get("recordType"),r?n=l(r.ATTRS):o(t)&&t.length&&(n=l(t[0])),n&&this.set("columns",n)),this._initColumns(),this._eventHandles={},this._initCoreEvents()},_setColumnMap:function(e){function n(e){var r,i,s,o;for(r=0,i=e.length;r<i;++r)s=e[r],o=s.key,o&&!t[o]&&(t[o]=s),t[s._id]=s,s.children&&n(s.children)}var t={};n(e),this._columnMap=t},_setColumns:function(t){function f(e){var t={},n,u,l;r.push(e),i.push(t);for(n in e)e.hasOwnProperty(n)&&(u=e[n],o(u)?t[n]=u.slice():s(u,!0)?(l=a(u,r),t[n]=l===-1?f(u):i[l]):t[n]=e[n]);return t}function l(e){return e=e.replace(/\s+/,"-"),n[e]?e+=n[e]++:n[e]=1,e}function c(t,n){var r=[],i,s,a,h;for(i=0,s=t.length;i<s;++i)r[i]=a=u(t[i])?{key:t[i]}:f(t[i]),h=e.stamp(a),a.id||(a.id=h),a.field&&(a.name=a.field),n?a._parent=n:delete a._parent,a._id=l(a.name||a.key||a.id),o(a.children)&&(a.children=c(a.children,a));return r}var n={},r=[],i=[],a=e.Array.indexOf;return t&&c(t)},_setColumnset:function(e){return this.set("columns",e),o(e)?e:n},_setData:function(e){e===null&&(e=[]);if(o(e))this._initDataProperty(),this.data.reset(e,{silent:!0}),e=this.data;else if(!e||!e.each||!e.toJSON)e=n;return e},_setRecordset:function(t){var n;return t&&e.Recordset&&t instanceof e.Recordset&&(n=[],t.each(function(e){n.push(e.get("data"))}),t=n),this.set("data",t),t},_setRecordType:function(e){var t;return i(e)&&e.prototype.toJSON&&e.prototype.setAttrs?t=e:s(e)&&(t=this._createRecordClass(e)),t||n}})},"3.7.3",{requires:["escape","model-list","node-event-delegate"]});
diff --git a/js/yui3/datatable-datasource-deprecated/datatable-datasource-deprecated-min.js b/js/yui3/datatable-datasource-deprecated/datatable-datasource-deprecated-min.js
new file mode 100644
index 000000000..01ae3e1b1
--- /dev/null
+++ b/js/yui3/datatable-datasource-deprecated/datatable-datasource-deprecated-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-datasource-deprecated",function(b){function a(){a.superclass.constructor.apply(this,arguments);}b.mix(a,{NS:"datasource",NAME:"dataTableDataSource",ATTRS:{datasource:{setter:"_setDataSource"},initialRequest:{setter:"_setInitialRequest"}}});b.extend(a,b.Plugin.Base,{_setDataSource:function(c){return c||new b.DataSource.Local(c);},_setInitialRequest:function(c){},initializer:function(c){if(!b.Lang.isUndefined(c.initialRequest)){this.load({request:c.initialRequest});}},load:function(c){c=c||{};c.request=c.request||this.get("initialRequest");c.callback=c.callback||{success:b.bind(this.onDataReturnInitializeTable,this),failure:b.bind(this.onDataReturnInitializeTable,this),argument:this.get("host").get("state")};var d=(c.datasource||this.get("datasource"));if(d){d.sendRequest(c);}},onDataReturnInitializeTable:function(d){var c=(d.response&&d.response.results)||[];this.get("host").get("recordset").set("records",c);}});b.namespace("Plugin").DataTableDataSource=a;},"3.7.3",{requires:["datatable-base-deprecated","plugin","datasource-local"]}); \ No newline at end of file
diff --git a/js/yui3/datatable-datasource/datatable-datasource-min.js b/js/yui3/datatable-datasource/datatable-datasource-min.js
new file mode 100644
index 000000000..677438dd2
--- /dev/null
+++ b/js/yui3/datatable-datasource/datatable-datasource-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-datasource",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}e.mix(n,{NS:"datasource",NAME:"dataTableDataSource",ATTRS:{datasource:{setter:"_setDataSource"},initialRequest:{setter:"_setInitialRequest"}}}),e.extend(n,e.Plugin.Base,{_setDataSource:function(t){return t||new e.DataSource.Local(t)},_setInitialRequest:function(e){},initializer:function(t){e.Lang.isUndefined(t.initialRequest)||this.load({request:t.initialRequest})},load:function(t){t=t||{},t.request=t.request||this.get("initialRequest"),t.callback=t.callback||{success:e.bind(this.onDataReturnInitializeTable,this),failure:e.bind(this.onDataReturnInitializeTable,this),argument:this.get("host").get("state")};var n=t.datasource||this.get("datasource");n&&n.sendRequest(t)},onDataReturnInitializeTable:function(e){var t=e.response&&e.response.results||[];this.get("host").set("data",t)}}),e.namespace("Plugin").DataTableDataSource=n},"3.7.3",{requires:["datatable-base","plugin","datasource-local"]});
diff --git a/js/yui3/datatable-head/datatable-head-min.js b/js/yui3/datatable-head/datatable-head-min.js
new file mode 100644
index 000000000..42c017034
--- /dev/null
+++ b/js/yui3/datatable-head/datatable-head-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-head",function(e,t){var n=e.Lang,r=n.sub,i=n.isArray,s=e.Array;e.namespace("DataTable").HeaderView=e.Base.create("tableHeader",e.View,[],{CELL_TEMPLATE:'<th id="{id}" colspan="{_colspan}" rowspan="{_rowspan}" class="{className}" scope="col" {_id}{abbr}>{content}</th>',ROW_TEMPLATE:"<tr>{content}</tr>",THEAD_TEMPLATE:'<thead class="{className}"></thead>',getClassName:function(){var t=this.host,n=t&&t.constructor.NAME||this.constructor.NAME;return t&&t.getClassName?t.getClassName.apply(t,arguments):e.ClassNameManager.getClassName.apply(e.ClassNameManager,[n].concat(s(arguments,0,!0)))},render:function(){var t=this.get("container"),n=this.theadNode||(this.theadNode=this._createTHeadNode()),i=this.columns,s={_colspan:1,_rowspan:1,abbr:""},o,u,a,f,l,c,h,p;if(n&&i){c="";if(i.length)for(o=0,u=i.length;o<u;++o){h="";for(a=0,f=i[o].length;a<f;++a)l=i[o][a],p=e.merge(s,l,{className:this.getClassName("header"),content:l.label||l.key||"Column "+(a+1)}),p._id=l._id?' data-yui3-col-id="'+l._id+'"':"",l.abbr&&(p.abbr=' abbr="'+l.abbr+'"'),l.className&&(p.className+=" "+l.className),l._first&&(p.className+=" "+this.getClassName("first","header")),l._id&&(p.className+=" "+this.getClassName("col",l._id)),h+=r(l.headerTemplate||this.CELL_TEMPLATE,p);c+=r(this.ROW_TEMPLATE,{content:h})}n.setHTML(c),n.get("parentNode")!==t&&t.insertBefore(n,t.one("tfoot, tbody"))}return this.bindUI(),this},_afterColumnsChange:function(e){this.columns=this._parseColumns(e.newVal),this.render()},bindUI:function(){this._eventHandles.columnsChange||(this._eventHandles.columnsChange=this.after("columnsChange",e.bind("_afterColumnsChange",this)))},_createTHeadNode:function(){return e.Node.create(r(this.THEAD_TEMPLATE,{className:this.getClassName("columns")}))},destructor:function(){(new e.EventHandle(e.Object.values(this._eventHandles))).detach()},initializer:function(e){this.host=e.host,this.columns=this._parseColumns(e.columns),this._eventHandles=[]},_parseColumns:function(t){var n=[],r=[],s=1,o,u,a,f,l,c,h,p;if(i(t)&&t.length){t=t.slice(),r.push([t,-1]);while(r.length){o=r[r.length-1],u=o[0],c=o[1]+1;for(h=u.length;c<h;++c){u[c]=a=e.merge(u[c]),f=a.children,e.stamp(a),a.id||(a.id=e.guid());if(i(f)&&f.length){r.push([f,-1]),o[1]=c,s=Math.max(s,r.length);break}a._colspan=1}if(c>=h){if(r.length>1){o=r[r.length-2],l=o[0][o[1]],l._colspan=0;for(c=0,h=u.length;c<h;++c)u[c]._parent=l,l._colspan+=u[c]._colspan}r.pop()}}for(c=0;c<s;++c)n.push([]);r.push([t,-1]);while(r.length){o=r[r.length-1],u=o[0],c=o[1]+1;for(h=u.length;c<h;++c){a=u[c],f=a.children,n[r.length-1].push(a),o[1]=c,a._headers=[a.id];for(p=r.length-2;p>=0;--p)l=r[p][0][r[p][1]],a._headers.unshift(l.id);if(f&&f.length){r.push([f,-1]);break}a._rowspan=s-r.length+1}c>=h&&r.pop()}}for(c=0,h=n.length;c<h;c+=a._rowspan)a=n[c][0],a._first=!0;return n}})},"3.7.3",{requires:["datatable-core","view","classnamemanager"]});
diff --git a/js/yui3/datatable-message/assets/datatable-message-core.css b/js/yui3/datatable-message/assets/datatable-message-core.css
new file mode 100644
index 000000000..6b88f8a3f
--- /dev/null
+++ b/js/yui3/datatable-message/assets/datatable-message-core.css
@@ -0,0 +1,14 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-message {
+ display: none;
+}
+
+.yui3-datatable-message-visible .yui3-datatable-message {
+ display: block;
+ display: table-row-group;
+}
diff --git a/js/yui3/datatable-message/assets/skins/night/datatable-message.css b/js/yui3/datatable-message/assets/skins/night/datatable-message.css
new file mode 100644
index 000000000..fa17416a3
--- /dev/null
+++ b/js/yui3/datatable-message/assets/skins/night/datatable-message.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-message{display:none}.yui3-datatable-message-visible .yui3-datatable-message{display:block;display:table-row-group}.yui3-skin-night .yui3-datatable-message-content{background-color:#0e0e0e;border:0 none;border-bottom:1px solid #303030;padding:4px 10px}#yui3-css-stamp.skin-night-datatable-message{display:none}
diff --git a/js/yui3/datatable-message/assets/skins/sam/datatable-message.css b/js/yui3/datatable-message/assets/skins/sam/datatable-message.css
new file mode 100644
index 000000000..bc6ffee49
--- /dev/null
+++ b/js/yui3/datatable-message/assets/skins/sam/datatable-message.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-message{display:none}.yui3-datatable-message-visible .yui3-datatable-message{display:block;display:table-row-group}.yui3-skin-sam .yui3-datatable-message-content{border:0 none;border-bottom:1px solid #cbcbcb;padding:4px 10px}#yui3-css-stamp.skin-sam-datatable-message{display:none}
diff --git a/js/yui3/datatable-message/datatable-message-min.js b/js/yui3/datatable-message/datatable-message-min.js
new file mode 100644
index 000000000..c60edeb4b
--- /dev/null
+++ b/js/yui3/datatable-message/datatable-message-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-message",function(e,t){var n;e.namespace("DataTable").Message=n=function(){},n.ATTRS={showMessages:{value:!0,validator:e.Lang.isBoolean}},e.mix(n.prototype,{MESSAGE_TEMPLATE:'<tbody class="{className}"><tr><td class="{contentClass}" colspan="{colspan}"></td></tr></tbody>',hideMessage:function(){return this.get("boundingBox").removeClass(this.getClassName("message","visible")),this},showMessage:function(e){var t=this.getString(e)||e;return this._messageNode||this._initMessageNode(),this.get("showMessages")&&(t?(this._messageNode.one("."+this.getClassName("message","content")).setHTML(t),this.get("boundingBox").addClass(this.getClassName("message","visible"))):this.hideMessage()),this},_afterMessageColumnsChange:function(e){var t;this._messageNode&&(t=this._messageNode.one("."+this.getClassName("message","content")),t&&t.set("colSpan",this._displayColumns.length))},_afterMessageDataChange:function(e){this._uiSetMessage()},_afterShowMessagesChange:function(e){e.newVal?this._uiSetMessage(e):this._messageNode&&(this.get("boundingBox").removeClass(this.getClassName("message","visible")),this._messageNode.remove().destroy(!0),this._messageNode=null)},_bindMessageUI:function(){this.after(["dataChange","*:add","*:remove","*:reset"],e.bind("_afterMessageDataChange",this)),this.after("columnsChange",e.bind("_afterMessageColumnsChange",this)),this.after("showMessagesChange",e.bind("_afterShowMessagesChange",this))},initializer:function(){this._initMessageStrings(),this.get("showMessages")&&this.after("renderBody",e.bind("_initMessageNode",this)),this.after(e.bind("_bindMessageUI",this),this,"bindUI"),this.after(e.bind("_syncMessageUI",this),this,"syncUI")},_initMessageNode:function(){this._messageNode||(this._messageNode=e.Node.create(e.Lang.sub(this.MESSAGE_TEMPLATE,{className:this.getClassName("message"),contentClass:this.getClassName("message","content"),colspan:this._displayColumns.length||1})),this._tableNode.insertBefore(this._messageNode,this._tbodyNode))},_initMessageStrings:function(){this.set("strings",e.mix(this.get("strings")||{},e.Intl.get("datatable-message")))},_syncMessageUI:function(){this._uiSetMessage()},_uiSetMessage:function(e){this.data.size()?this.hideMessage():this.showMessage(e&&e.message||"emptyMessage")}}),e.Lang.isFunction(e.DataTable)&&e.Base.mix(e.DataTable,[n])},"3.7.3",{requires:["datatable-base"],lang:["en"],skinnable:!0});
diff --git a/js/yui3/datatable-message/lang/datatable-message.js b/js/yui3/datatable-message/lang/datatable-message.js
new file mode 100644
index 000000000..0459385c9
--- /dev/null
+++ b/js/yui3/datatable-message/lang/datatable-message.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-message",function(e){e.Intl.add("datatable-message","",{emptyMessage:"No data to display",loadingMessage:"Loading..."})},"3.7.3");
diff --git a/js/yui3/datatable-message/lang/datatable-message_en.js b/js/yui3/datatable-message/lang/datatable-message_en.js
new file mode 100644
index 000000000..8f73cce15
--- /dev/null
+++ b/js/yui3/datatable-message/lang/datatable-message_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-message_en",function(e){e.Intl.add("datatable-message","en",{emptyMessage:"No data to display",loadingMessage:"Loading..."})},"3.7.3");
diff --git a/js/yui3/datatable-mutable/datatable-mutable-min.js b/js/yui3/datatable-mutable/datatable-mutable-min.js
new file mode 100644
index 000000000..7b194b6a3
--- /dev/null
+++ b/js/yui3/datatable-mutable/datatable-mutable-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-mutable",function(e,t){var n=e.Array,r=e.Lang,i=r.isString,s=r.isArray,o=r.isObject,u=r.isNumber,a=e.Array.indexOf,f;e.namespace("DataTable").Mutable=f=function(){},f.ATTRS={autoSync:{value:!1,validator:r.isBoolean}},e.mix(f.prototype,{addColumn:function(e,t){i(e)&&(e={key:e});if(e){if(arguments.length<2||!u(t)&&!s(t))t=this.get("columns").length;this.fire("addColumn",{column:e,index:t})}return this},modifyColumn:function(e,t){return i(t)&&(t={key:t}),o(t)&&this.fire("modifyColumn",{column:e,newColumnDef:t}),this},moveColumn:function(e,t){return e!==undefined&&(u(t)||s(t))&&this.fire("moveColumn",{column:e,index:t}),this},removeColumn:function(e){return e!==undefined&&this.fire("removeColumn",{column:e}),this},addRow:function(e,t){var r=t&&"sync"in t?t.sync:this.get("autoSync"),i,s,o,u,a;if(e&&this.data){i=this.data.add.apply(this.data,arguments);if(r){i=n(i),a=n(arguments,1,!0);for(o=0,u=i.length;o<u;++o)s=i[o],s.isNew()&&i[o].save.apply(i[o],a)}}return this},removeRow:function(e,t){var r=this.data,i=t&&"sync"in t?t.sync:this.get("autoSync"),s,u,a,f,l;o(e)&&e instanceof this.get("recordType")?u=e:r&&e!==undefined&&(u=r.getById(e)||r.getByClientId(e)||r.item(e));if(u){l=n(arguments,1,!0),s=r.remove.apply(r,[u].concat(l));if(i){o(l[0])||l.unshift({}),l[0]["delete"]=!0,s=n(s);for(a=0,f=s.length;a<f;++a)u=s[a],u.destroy.apply(u,l)}}return this},modifyRow:function(e,t,r){var i=this.data,s=r&&"sync"in r?r.sync:this.get("autoSync"),u,a;return o(e)&&e instanceof this.get("recordType")?u=e:i&&e!==undefined&&(u=i.getById(e)||i.getByClientId(e)||i.item(e)),u&&o(t)&&(a=n(arguments,1,!0),u.setAttrs.apply(u,a),s&&!u.isNew()&&u.save.apply(u,a)),this},_defAddColumnFn:function(e){var t=n(e.index),r=this.get("columns"),i=r,s,o;for(s=0,o=t.length-1;i&&s<o;++s)i=i[t[s]]&&i[t[s]].children;i&&(i.splice(t[s],0,e.column),this.set("columns",r,{originEvent:e}))},_defModifyColumnFn:function(t){var n=this.get("columns"),r=this.getColumn(t.column);r&&(e.mix(r,t.newColumnDef,!0),this.set("columns",n,{originEvent:t}))},_defMoveColumnFn:function(e){var t=this.get("columns"),r=this.getColumn(e.column),i=n(e.index),s,o,u,f,l;if(r){s=r._parent?r._parent.children:t,o=a(s,r);if(o>-1){u=t;for(f=0,l=i.length-1;u&&f<l;++f)u=u[i[f]]&&u[i[f]].children;u&&(l=u.length,s.splice(o,1),i=i[f],l>u.lenth&&o<i&&i--,u.splice(i,0,r),this.set("columns",t,{originEvent:e}))}}},_defRemoveColumnFn:function(t){var n=this.get("columns"),r=this.getColumn(t.column),i,s;r&&(i=r._parent?r._parent.children:n,s=e.Array.indexOf(i,r),s>-1&&(i.splice(s,1),this.set("columns",n,{originEvent:t})))},initializer:function(){this.publish({addColumn:{defaultFn:e.bind("_defAddColumnFn",this)},removeColumn:{defaultFn:e.bind("_defRemoveColumnFn",this)},moveColumn:{defaultFn:e.bind("_defMoveColumnFn",this)},modifyColumn:{defaultFn:e.bind("_defModifyColumnFn",this)}})}}),f.prototype.addRows=f.prototype.addRow,r.isFunction(e.DataTable)&&e.Base.mix(e.DataTable,[f])},"3.7.3",{requires:["datatable-base"]});
diff --git a/js/yui3/datatable-scroll-deprecated/datatable-scroll-deprecated-min.js b/js/yui3/datatable-scroll-deprecated/datatable-scroll-deprecated-min.js
new file mode 100644
index 000000000..7dae4f152
--- /dev/null
+++ b/js/yui3/datatable-scroll-deprecated/datatable-scroll-deprecated-min.js
@@ -0,0 +1,8 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-scroll-deprecated",function(b){var m=b.Node,k=b.Lang,o=b.UA,g=b.ClassNameManager.getClassName,n="datatable",a=g(n,"hd"),e=g(n,"bd"),d=g(n,"data"),l=g(n,"liner"),j=g(n,"scrollable"),i='<div class="'+a+'"></div>',c='<div class="'+e+'"></div>',h="<table></table>",f=b.cached(function(){var q=b.one("body").appendChild('<div style="position:absolute;visibility:hidden;overflow:scroll;width:20px;"><p style="height:1px"/></div>'),r=q.get("offsetWidth")-q.get("clientWidth");q.remove(true);return r;});function p(){p.superclass.constructor.apply(this,arguments);}b.mix(p,{NS:"scroll",NAME:"dataTableScroll",ATTRS:{width:{value:undefined,writeOnce:"initOnly"},height:{value:undefined,writeOnce:"initOnly"},_scroll:{valueFn:function(){var q=this.get("width"),r=this.get("height");if(q&&r){return"xy";}else{if(q){return"x";}else{if(r){return"y";}else{return null;}}}}},COLOR_COLUMNFILLER:{value:"#f2f2f2",validator:k.isString,setter:function(q){if(this._headerContainerNode){this._headerContainerNode.setStyle("backgroundColor",q);}}}}});b.extend(p,b.Plugin.Base,{_parentTableNode:null,_parentTheadNode:null,_parentTbodyNode:null,_parentMsgNode:null,_parentContainer:null,_bodyContainerNode:null,_headerContainerNode:null,initializer:function(q){var r=this.get("host");this._parentContainer=r.get("contentBox");this._parentContainer.addClass(j);this._setUpNodes();},_setUpNodes:function(){this.afterHostMethod("_addTableNode",this._setUpParentTableNode);this.afterHostMethod("_addTheadNode",this._setUpParentTheadNode);this.afterHostMethod("_addTbodyNode",this._setUpParentTbodyNode);this.afterHostMethod("_addMessageNode",this._setUpParentMessageNode);this.afterHostMethod("renderUI",this.renderUI);this.afterHostMethod("bindUI",this.bindUI);this.afterHostMethod("syncUI",this.syncUI);if(this.get("_scroll")!=="x"){this.afterHostMethod("_attachTheadThNode",this._attachTheadThNode);this.afterHostMethod("_attachTbodyTdNode",this._attachTbodyTdNode);}},_setUpParentTableNode:function(){this._parentTableNode=this.get("host")._tableNode;},_setUpParentTheadNode:function(){this._parentTheadNode=this.get("host")._theadNode;},_setUpParentTbodyNode:function(){this._parentTbodyNode=this.get("host")._tbodyNode;},_setUpParentMessageNode:function(){this._parentMsgNode=this.get("host")._msgNode;},renderUI:function(){this._createBodyContainer();this._createHeaderContainer();this._setContentBoxDimensions();},bindUI:function(){this._bodyContainerNode.on("scroll",b.bind("_onScroll",this));this.afterHostEvent("recordsetChange",this.syncUI);this.afterHostEvent("recordset:recordsChange",this.syncUI);},syncUI:function(){this._removeCaptionNode();this._syncWidths();this._syncScroll();},_removeCaptionNode:function(){this.get("host")._captionNode.remove();},_syncWidths:function(){var t=this._parentContainer.one("."+a),q=this._parentContainer.one("."+e),v=t.all("thead ."+l),u=q.one("."+d+" tr"),s=u&&u.all("."+l),r=(o.ie)?"offsetWidth":"clientWidth";if(s&&s.size()){v.each(function(B,y){var w=s.item(y),x=B.get(r),A=w.get(r),z=Math.max(x,A);z-=(parseInt(B.getComputedStyle("paddingLeft"),10)|0)+(parseInt(B.getComputedStyle("paddingRight"),10)|0);B.setStyle("width",z+"px");w.setStyle("width",z+"px");});}},_attachTheadThNode:function(r){var q=r.column.get("width");if(q){r.th.one("."+l).setStyles({width:q,overflow:"hidden"});}},_attachTbodyTdNode:function(r){var q=r.column.get("width");if(q){r.td.one("."+l).setStyles({width:q,overflow:"hidden"});}},_createBodyContainer:function(){var q=m.create(c);this._bodyContainerNode=q;this._setStylesForTbody();q.appendChild(this._parentTableNode);this._parentContainer.appendChild(q);},_createHeaderContainer:function(){var r=m.create(i),q=m.create(h);this._headerContainerNode=r;this._setStylesForThead();q.appendChild(this._parentTheadNode);r.appendChild(q);this._parentContainer.prepend(r);},_setStylesForTbody:function(){var r=this.get("_scroll"),q=this.get("width")||"",t=this.get("height")||"",s=this._bodyContainerNode,u={width:"",height:t};if(r==="x"){u.overflowY="hidden";u.width=q;}else{if(r==="y"){u.overflowX="hidden";}else{if(r==="xy"){u.width=q;}else{u.overflowX="hidden";u.overflowY="hidden";u.width=q;}}}s.setStyles(u);return s;},_setStylesForThead:function(){var q=this.get("width")||"",r=this._headerContainerNode;r.setStyles({"width":q,"overflow":"hidden"});},_setContentBoxDimensions:function(){if(this.get("_scroll")==="y"||(!this.get("width"))){this._parentContainer.setStyle("width","auto");}},_onScroll:function(){this._headerContainerNode.set("scrollLeft",this._bodyContainerNode.get("scrollLeft"));},_syncScroll:function(){this._syncScrollX();this._syncScrollY();this._syncScrollOverhang();if(o.opera){this._headerContainerNode.set("scrollLeft",this._bodyContainerNode.get("scrollLeft"));if(!this.get("width")){document.body.style+="";}}},_syncScrollY:function(){var q=this._parentTbodyNode,s=this._bodyContainerNode,r;if(!this.get("width")){r=(s.get("scrollHeight")>s.get("clientHeight"))?(q.get("parentNode").get("clientWidth")+f())+"px":(q.get("parentNode").get("clientWidth")+2)+"px";this._parentContainer.setStyle("width",r);}},_syncScrollX:function(){var q=this._parentTbodyNode,s=this._bodyContainerNode,r;this._headerContainerNode.set("scrollLeft",this._bodyContainerNode.get("scrollLeft"));if(!this.get("height")&&(o.ie)){r=(s.get("scrollWidth")>s.get("offsetWidth"))?(q.get("parentNode").get("offsetHeight")+f())+"px":q.get("parentNode").get("offsetHeight")+"px";s.setStyle("height",r);}if(q.get("rows").size()){this._parentMsgNode.get("parentNode").setStyle("width","");}else{this._parentMsgNode.get("parentNode").setStyle("width",this._parentTheadNode.get("parentNode").get("offsetWidth")+"px");}},_syncScrollOverhang:function(){var q=this._bodyContainerNode,r=1;if((q.get("scrollHeight")>q.get("clientHeight"))||(q.get("scrollWidth")>q.get("clientWidth"))){r=18;}this._setOverhangValue(r);if(o.ie!==0&&this.get("_scroll")==="y"&&this._bodyContainerNode.get("scrollHeight")>this._bodyContainerNode.get("offsetHeight")){this._headerContainerNode.setStyle("width",this._parentContainer.get("width"));
+}},_setOverhangValue:function(r){var t=this.get("host"),v=t.get("columnset").get("definitions"),q=v.length,u=r+"px solid "+this.get("COLOR_COLUMNFILLER"),s=m.all("#"+this._parentContainer.get("id")+" ."+a+" table thead th");s.item(q-1).setStyle("borderRight",u);}});b.namespace("Plugin").DataTableScroll=p;},"3.7.3",{requires:["datatable-base-deprecated","plugin"]}); \ No newline at end of file
diff --git a/js/yui3/datatable-scroll/assets/datatable-scroll-core.css b/js/yui3/datatable-scroll/assets/datatable-scroll-core.css
new file mode 100644
index 000000000..ec1d7a7e7
--- /dev/null
+++ b/js/yui3/datatable-scroll/assets/datatable-scroll-core.css
@@ -0,0 +1,77 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* foundational CSS */
+.yui3-datatable-scrollable-x {
+ _overflow-x: hidden;
+ _position: relative;
+}
+
+.yui3-datatable-scrollable-y,
+.yui3-datatable-scrollable-y .yui3-datatable-x-scroller {
+ _overflow-y: hidden;
+ _position: relative;
+}
+
+.yui3-datatable-y-scroller-container {
+ overflow-x: hidden;
+ position: relative;
+}
+
+.yui3-datatable-scrollable-y .yui3-datatable-content {
+ /* To allow absolute positioning of virtual scrollbar */
+ position: relative;
+}
+
+.yui3-datatable-scrollable-y .yui3-datatable-table .yui3-datatable-columns {
+ /* Prevent masked headers from showing during momentum scrolling */
+ visibility: hidden;
+}
+
+.yui3-datatable-scroll-columns {
+ position: absolute;
+ width: 100%;
+ z-index: 2;
+}
+
+.yui3-datatable-y-scroller,
+.yui3-datatable-scrollable-x .yui3-datatable-caption-table {
+ width: 100%;
+}
+
+.yui3-datatable-x-scroller {
+ position: relative;
+ overflow-x: scroll;
+ overflow-y: hidden;
+}
+
+.yui3-datatable-scrollable-y .yui3-datatable-y-scroller {
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ z-index: 1;
+ -webkit-overflow-scrolling: touch;
+}
+
+.yui3-datatable-scrollbar {
+ position: absolute;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ z-index: 2;
+}
+
+.yui3-datatable-scrollbar div {
+ position: absolute;
+ width: 1px;
+ visibility: hidden;
+}
+
+/* Removed because it prevented cmd + zoom resizing in Chrome (at least) */
+/*
+.yui3-datatable-header {
+ -webkit-text-size-adjust: none;
+}
+*/
diff --git a/js/yui3/datatable-scroll/assets/skins/night/datatable-scroll.css b/js/yui3/datatable-scroll/assets/skins/night/datatable-scroll.css
new file mode 100644
index 000000000..4642ac414
--- /dev/null
+++ b/js/yui3/datatable-scroll/assets/skins/night/datatable-scroll.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-scrollable-x{_overflow-x:hidden;_position:relative}.yui3-datatable-scrollable-y,.yui3-datatable-scrollable-y .yui3-datatable-x-scroller{_overflow-y:hidden;_position:relative}.yui3-datatable-y-scroller-container{overflow-x:hidden;position:relative}.yui3-datatable-scrollable-y .yui3-datatable-content{position:relative}.yui3-datatable-scrollable-y .yui3-datatable-table .yui3-datatable-columns{visibility:hidden}.yui3-datatable-scroll-columns{position:absolute;width:100%;z-index:2}.yui3-datatable-y-scroller,.yui3-datatable-scrollable-x .yui3-datatable-caption-table{width:100%}.yui3-datatable-x-scroller{position:relative;overflow-x:scroll;overflow-y:hidden}.yui3-datatable-scrollable-y .yui3-datatable-y-scroller{position:relative;overflow-x:hidden;overflow-y:scroll;z-index:1;-webkit-overflow-scrolling:touch}.yui3-datatable-scrollbar{position:absolute;overflow-x:hidden;overflow-y:scroll;z-index:2}.yui3-datatable-scrollbar div{position:absolute;width:1px;visibility:hidden}.yui3-skin-sam .yui3-datatable-scroll-columns{border-collapse:separate;border-spacing:0;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;margin:0;padding:0;top:0;left:0}.yui3-skin-sam .yui3-datatable-scroll-columns .yui3-datatable-header{padding:0}.yui3-skin-sam .yui3-datatable-x-scroller,.yui3-skin-sam .yui3-datatable-y-scroller-container{border:1px solid #303030;border-left-color:#323434}.yui3-skin-sam .yui3-datatable-scrollable-x .yui3-datatable-y-scroller-container,.yui3-skin-sam .yui3-datatable-x-scroller .yui3-datatable-table,.yui3-skin-sam .yui3-datatable-y-scroller .yui3-datatable-table{border:0 none}#yui3-css-stamp.skin-night-datatable-scroll{display:none}
diff --git a/js/yui3/datatable-scroll/assets/skins/sam/datatable-scroll.css b/js/yui3/datatable-scroll/assets/skins/sam/datatable-scroll.css
new file mode 100644
index 000000000..13ba4e560
--- /dev/null
+++ b/js/yui3/datatable-scroll/assets/skins/sam/datatable-scroll.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-scrollable-x{_overflow-x:hidden;_position:relative}.yui3-datatable-scrollable-y,.yui3-datatable-scrollable-y .yui3-datatable-x-scroller{_overflow-y:hidden;_position:relative}.yui3-datatable-y-scroller-container{overflow-x:hidden;position:relative}.yui3-datatable-scrollable-y .yui3-datatable-content{position:relative}.yui3-datatable-scrollable-y .yui3-datatable-table .yui3-datatable-columns{visibility:hidden}.yui3-datatable-scroll-columns{position:absolute;width:100%;z-index:2}.yui3-datatable-y-scroller,.yui3-datatable-scrollable-x .yui3-datatable-caption-table{width:100%}.yui3-datatable-x-scroller{position:relative;overflow-x:scroll;overflow-y:hidden}.yui3-datatable-scrollable-y .yui3-datatable-y-scroller{position:relative;overflow-x:hidden;overflow-y:scroll;z-index:1;-webkit-overflow-scrolling:touch}.yui3-datatable-scrollbar{position:absolute;overflow-x:hidden;overflow-y:scroll;z-index:2}.yui3-datatable-scrollbar div{position:absolute;width:1px;visibility:hidden}.yui3-skin-sam .yui3-datatable-scroll-columns{border-collapse:separate;border-spacing:0;font-family:arial,sans-serif;margin:0;padding:0;top:0;left:0}.yui3-skin-sam .yui3-datatable-scroll-columns .yui3-datatable-header{padding:0}.yui3-skin-sam .yui3-datatable-x-scroller,.yui3-skin-sam .yui3-datatable-y-scroller-container{border:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable-scrollable-x .yui3-datatable-y-scroller-container,.yui3-skin-sam .yui3-datatable-x-scroller .yui3-datatable-table,.yui3-skin-sam .yui3-datatable-y-scroller .yui3-datatable-table{border:0 none}#yui3-css-stamp.skin-sam-datatable-scroll{display:none}
diff --git a/js/yui3/datatable-scroll/datatable-scroll-min.js b/js/yui3/datatable-scroll/datatable-scroll-min.js
new file mode 100644
index 000000000..163ed1d24
--- /dev/null
+++ b/js/yui3/datatable-scroll/datatable-scroll-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-scroll",function(e,t){function u(e,t){return parseInt(e.getComputedStyle(t),10)|0}var n=e.Lang,r=n.isString,i=n.isNumber,s=n.isArray,o;e.DataTable.Scrollable=o=function(){},o.ATTRS={scrollable:{value:!1,setter:"_setScrollable"}},e.mix(o.prototype,{scrollTo:function(t){var n;return t&&this._tbodyNode&&(this._yScrollNode||this._xScrollNode)&&(s(t)?n=this.getCell(t):i(t)?n=this.getRow(t):r(t)?n=this._tbodyNode.one("#"+t):t instanceof e.Node&&t.ancestor(".yui3-datatable")===this.get("boundingBox")&&(n=t),n&&n.scrollIntoView()),this},_CAPTION_TABLE_TEMPLATE:'<table class="{className}" role="presentation"></table>',_SCROLL_LINER_TEMPLATE:'<div class="{className}"></div>',_SCROLLBAR_TEMPLATE:'<div class="{className}"><div></div></div>',_X_SCROLLER_TEMPLATE:'<div class="{className}"></div>',_Y_SCROLL_HEADER_TEMPLATE:'<table cellspacing="0" aria-hidden="true" class="{className}"></table>',_Y_SCROLLER_TEMPLATE:'<div class="{className}"><div class="{scrollerClassName}"></div></div>',_addScrollbarPadding:function(){var t=this._yScrollHeader,n="."+this.getClassName("header"),r,i,s,o,u;if(t){r=e.DOM.getScrollbarWidth()+"px",i=t.all("tr");for(o=0,u=i.size();o<u;o+=+s.get("rowSpan"))s=i.item(o).all(n).pop(),s.setStyle("paddingRight",r)}},_afterScrollableChange:function(t){var n=this._xScrollNode;this._xScroll&&n&&(this._yScroll&&!this._yScrollNode?n.setStyle("paddingRight",e.DOM.getScrollbarWidth()+"px"):!this._yScroll&&this._yScrollNode&&n.setStyle("paddingRight","")),this._syncScrollUI()},_afterScrollCaptionChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollColumnsChange:function(e){if(this._xScroll||this._yScroll)this._yScroll&&this._yScrollHeader&&this._syncScrollHeaders(),this._syncScrollUI()},_afterScrollDataChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_afterScrollHeightChange:function(e){this._yScroll&&this._syncScrollUI()},_afterScrollSort:function(e){var t,n;this._yScroll&&this._yScrollHeader&&(n="."+this.getClassName("header"),t=this._theadNode.all(n),this._yScrollHeader.all(n).each(function(e,n){e.set("className",t.item(n).get("className"))}))},_afterScrollWidthChange:function(e){(this._xScroll||this._yScroll)&&this._syncScrollUI()},_bindScrollbar:function(){var t=this._scrollbarNode,n=this._yScrollNode;t&&n&&!this._scrollbarEventHandle&&(this._scrollbarEventHandle=new e.Event.Handle([t.on("scroll",this._syncScrollPosition,this),n.on("scroll",this._syncScrollPosition,this)]))},_bindScrollResize:function(){this._scrollResizeHandle||(this._scrollResizeHandle=e.on("resize",this._syncScrollUI,null,this))},_bindScrollUI:function(){this.after({columnsChange:e.bind("_afterScrollColumnsChange",this),heightChange:e.bind("_afterScrollHeightChange",this),widthChange:e.bind("_afterScrollWidthChange",this),captionChange:e.bind("_afterScrollCaptionChange",this),scrollableChange:e.bind("_afterScrollableChange",this),sort:e.bind("_afterScrollSort",this)}),this.after(["dataChange","*:add","*:remove","*:reset","*:change"],e.bind("_afterScrollDataChange",this))},_clearScrollLock:function(){this._scrollLock&&(this._scrollLock.cancel(),delete this._scrollLock)},_createScrollbar:function(){var t=this._scrollbarNode;return t||(t=this._scrollbarNode=e.Node.create(e.Lang.sub(this._SCROLLBAR_TEMPLATE,{className:this.getClassName("scrollbar")})),t.setStyle("width",e.DOM.getScrollbarWidth()+1+"px")),t},_createScrollCaptionTable:function(){return this._captionTable||(this._captionTable=e.Node.create(e.Lang.sub(this._CAPTION_TABLE_TEMPLATE,{className:this.getClassName("caption","table")})),this._captionTable.empty()),this._captionTable},_createXScrollNode:function(){return this._xScrollNode||(this._xScrollNode=e.Node.create(e.Lang.sub(this._X_SCROLLER_TEMPLATE,{className:this.getClassName("x","scroller")}))),this._xScrollNode},_createYScrollHeader:function(){var t=this._yScrollHeader;return t||(t=this._yScrollHeader=e.Node.create(e.Lang.sub(this._Y_SCROLL_HEADER_TEMPLATE,{className:this.getClassName("scroll","columns")}))),t},_createYScrollNode:function(){var t;return this._yScrollNode||(t=this.getClassName("y","scroller"),this._yScrollContainer=e.Node.create(e.Lang.sub(this._Y_SCROLLER_TEMPLATE,{className:this.getClassName("y","scroller","container"),scrollerClassName:t})),this._yScrollNode=this._yScrollContainer.one("."+t)),this._yScrollContainer},_disableScrolling:function(){this._removeScrollCaptionTable(),this._disableXScrolling(),this._disableYScrolling(),this._unbindScrollResize(),this._uiSetWidth(this.get("width"))},_disableXScrolling:function(){this._removeXScrollNode()},_disableYScrolling:function(){this._removeYScrollHeader(),this._removeYScrollNode(),this._removeYScrollContainer(),this._removeScrollbar()},destructor:function(){this._unbindScrollbar(),this._unbindScrollResize(),this._clearScrollLock()},initializer:function(){this._setScrollProperties(),this.after(["scrollableChange","heightChange","widthChange"],this._setScrollProperties),this.after("renderView",e.bind("_syncScrollUI",this)),e.Do.after(this._bindScrollUI,this,"bindUI")},_removeScrollCaptionTable:function(){this._captionTable&&(this._captionNode&&this._tableNode.prepend(this._captionNode),this._captionTable.remove().destroy(!0),delete this._captionTable)},_removeXScrollNode:function(){var e=this._xScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._xScrollNode)},_removeYScrollContainer:function(){var e=this._yScrollContainer;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollContainer)},_removeYScrollHeader:function(){this._yScrollHeader&&(this._yScrollHeader.remove().destroy(!0),delete this._yScrollHeader)},_removeYScrollNode:function(){var e=this._yScrollNode;e&&(e.replace(e.get("childNodes").toFrag()),e.remove().destroy(!0),delete this._yScrollNode)},_removeScrollbar:function(){this._scrollbarNode&&(this._scrollbarNode.remove().destroy(!0),delete this._scrollbarNode),this._scrollbarEventHandle&&(this._scrollbarEventHandle.detach(),delete this._scrollbarEventHandle)},_setScrollable:function(t){return t===!0&&(t="xy"),r(t)&&(t=t.toLowerCase()),t===!1||t==="y"||t==="x"||t==="xy"?t:e.Attribute.INVALID_VALUE},_setScrollProperties:function(){var e=this.get("scrollable")||"",t=this.get("width"),n=this.get("height");this._xScroll=t&&e.indexOf("x")>-1,this._yScroll=n&&e.indexOf("y")>-1},_syncScrollPosition:function(t){var n=this._scrollbarNode,r=this._yScrollNode,i=t.currentTarget,s;if(n&&r){if(this._scrollLock&&this._scrollLock.source!==i)return;this._clearScrollLock(),this._scrollLock=e.later(300,this,this._clearScrollLock),this._scrollLock.source=i,s=i===n?r:n,s.set("scrollTop",i.get("scrollTop"))}},_syncScrollCaptionUI:function(){var t=this._captionNode,n=this._tableNode,r=this._captionTable,i;t?(i=t.getAttribute("id"),r||(r=this._createScrollCaptionTable(),this.get("contentBox").prepend(r)),t.get("parentNode").compareTo(r)||(r.empty().insert(t),i||(i=e.stamp(t),t.setAttribute("id",i)),n.setAttribute("aria-describedby",i))):r&&this._removeScrollCaptionTable()},_syncScrollColumnWidths:function(){var t=[];this._theadNode&&this._yScrollHeader&&(this._theadNode.all("."+this.getClassName("header")).each(function(n){t.push(e.UA.ie&&e.UA.ie<8?n.get("clientWidth")-u(n,"paddingLeft")-u(n,"paddingRight")+"px":n.getComputedStyle("width"))}),this._yScrollHeader.all("."+this.getClassName("scroll","liner")).each(function(e,n){e.setStyle("width",t[n])}))},_syncScrollHeaders:function(){var t=this._yScrollHeader,n=this._SCROLL_LINER_TEMPLATE,r=this.getClassName("scroll","liner"),i=this.getClassName("header"),s=this._theadNode.all("."+i);this._theadNode&&t&&(t.empty().appendChild(this._theadNode.cloneNode(!0)),t.all("[id]").removeAttribute("id"),t.all("."+i).each(function(t,i){var o=e.Node.create(e.Lang.sub(n,{className:r})),u=s.item(i);o.setStyle("padding",u.getComputedStyle("paddingTop")+" "+u.getComputedStyle("paddingRight")+" "+u.getComputedStyle("paddingBottom")+" "+u.getComputedStyle("paddingLeft")),o.appendChild(t.get("childNodes").toFrag()),t.appendChild(o)},this),this._syncScrollColumnWidths(),this._addScrollbarPadding())},_syncScrollUI:function(){var e=this._xScroll,t=this._yScroll,n=this._xScrollNode,r=this._yScrollNode,i=n&&n.get("scrollLeft"),s=r&&r.get("scrollTop");this._uiSetScrollable(),e||t?((this.get("width")||"").slice(-1)==="%"?this._bindScrollResize():this._unbindScrollResize(),this._syncScrollCaptionUI()):this._disableScrolling(),this._yScrollHeader&&this._yScrollHeader.setStyle("display","none"),e&&(t||this._disableYScrolling(),this._syncXScrollUI(t)),t&&(e||this._disableXScrolling(),this._syncYScrollUI(e)),i&&this._xScrollNode&&this._xScrollNode.set("scrollLeft",i),s&&this._yScrollNode&&this._yScrollNode.set("scrollTop",s)},_syncXScrollUI:function(t){var n=this._xScrollNode,r=this._yScrollContainer,i=this._tableNode,s=this.get("width"),o=this.get("boundingBox").get("offsetWidth"),a=e.DOM.getScrollbarWidth(),f,l;n||(n=this._createXScrollNode(),(r||i).replace(n).appendTo(n)),f=u(n,"borderLeftWidth")+u(n,"borderRightWidth"),n.setStyle("width",""),this._uiSetDim("width",""),t&&this._yScrollContainer&&this._yScrollContainer.setStyle("width",""),e.UA.ie&&e.UA.ie<8&&(i.setStyle("width",s),i.get("offsetWidth")),i.setStyle("width",""),l=i.get("offsetWidth"),i.setStyle("width",l+"px"),this._uiSetDim("width",s),n.setStyle("width",o-f+"px"),n.get("offsetWidth")-f>l&&(t?i.setStyle("width",n.get("offsetWidth")-f-a+"px"):i.setStyle("width","100%"))},_syncYScrollUI:function(t){var n=this._yScrollContainer,r=this._yScrollNode,i=this._xScrollNode,s=this._yScrollHeader,o=this._scrollbarNode,a=this._tableNode,f=this._theadNode,l=this._captionTable,c=this.get("boundingBox"),h=this.get("contentBox"),p=this.get("width"),d=c.get("offsetHeight"),v=e.DOM.getScrollbarWidth(),m;l&&!t&&l.setStyle("width",p||"100%"),n||(n=this._createYScrollNode(),r=this._yScrollNode,a.replace(n).appendTo(r)),m=t?i:n,t||a.setStyle("width",""),t&&(d-=v),r.setStyle("height",d-m.get("offsetTop")-u(m,"borderTopWidth")-u(m,"borderBottomWidth")+"px"),t?n.setStyle("width",a.get("offsetWidth")+v+"px"):this._uiSetYScrollWidth(p),l&&!t&&l.setStyle("width",n.get("offsetWidth")+"px"),f&&!s&&(s=this._createYScrollHeader(),n.prepend(s),this._syncScrollHeaders()),s&&(this._syncScrollColumnWidths(),s.setStyle("display",""),o||(o=this._createScrollbar(),this._bindScrollbar(),h.prepend(o)),this._uiSetScrollbarHeight(),this._uiSetScrollbarPosition(m))},_uiSetScrollable:function(){this.get("boundingBox").toggleClass(this.getClassName("scrollable","x"),this._xScroll).toggleClass(this.getClassName("scrollable","y"),this._yScroll)},_uiSetScrollbarHeight:function(){var e=this._scrollbarNode,t=this._yScrollNode,n=this._yScrollHeader;e&&t&&n&&(e.get("firstChild").setStyle("height",this._tbodyNode.get("scrollHeight")+"px"),e.setStyle("height",parseFloat(t.getComputedStyle("height"))-parseFloat(n.getComputedStyle("height"))+"px"))},_uiSetScrollbarPosition:function(t){var n=this._scrollbarNode,r=this._yScrollHeader;n&&t&&r&&n.setStyles({top:parseFloat(r.getComputedStyle("height"))+u(t,"borderTopWidth")+t.get("offsetTop")+"px",left:t.get("offsetWidth")-e.DOM.getScrollbarWidth()-1-u(t,"borderRightWidth")+"px"})},_uiSetYScrollWidth:function(t){var n=this._yScrollContainer,r=this._tableNode,i,s,o,u;n&&r&&(u=e.DOM.getScrollbarWidth(),t?(s=n.get("offsetWidth")-n.get("clientWidth")+u,n.setStyle("width",t),o=n.get("clientWidth")-s,r.setStyle("width",o+"px"),i=r.get("offsetWidth"),n.setStyle("width",i+u+"px")):(r.setStyle("width",""),n.setStyle("width",""),n.setStyle("width",r.get("offsetWidth")+u+"px")))},_unbindScrollbar:function(){this._scrollbarEventHandle&&this._scrollbarEventHandle.detach()},_unbindScrollResize:function(){this._scrollResizeHandle&&(this._scrollResizeHandle.detach(),delete this._scrollResizeHandle)}},!0),e.Base.mix(e.DataTable,[o])},"3.7.3",{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0});
diff --git a/js/yui3/datatable-sort-deprecated/datatable-sort-deprecated-min.js b/js/yui3/datatable-sort-deprecated/datatable-sort-deprecated-min.js
new file mode 100644
index 000000000..331c7810f
--- /dev/null
+++ b/js/yui3/datatable-sort-deprecated/datatable-sort-deprecated-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-sort-deprecated",function(g){var f=g.ClassNameManager.getClassName,h="datatable",b="column",d="asc",c="desc",a='<a class="{link_class}" title="{link_title}" href="{link_href}">{value}</a>';function e(){e.superclass.constructor.apply(this,arguments);}g.mix(e,{NS:"sort",NAME:"dataTableSort",ATTRS:{trigger:{value:{event:"click",selector:"th"},writeOnce:"initOnly"},lastSortedBy:{setter:"_setLastSortedBy",lazyAdd:false},template:{value:a},strings:{valueFn:function(){return g.Intl.get("datatable-sort-deprecated");}}}});g.extend(e,g.Plugin.Base,{initializer:function(j){var k=this.get("host"),i=this.get("trigger");k.get("recordset").plug(g.Plugin.RecordsetSort,{dt:k});k.get("recordset").sort.addTarget(k);this.doBefore("_createTheadThNode",this._beforeCreateTheadThNode);this.doBefore("_attachTheadThNode",this._beforeAttachTheadThNode);this.doBefore("_attachTbodyTdNode",this._beforeAttachTbodyTdNode);k.delegate(i.event,g.bind(this._onEventSortColumn,this),i.selector);k.after("recordsetSort:sort",function(){this._uiSetRecordset(this.get("recordset"));});this.on("lastSortedByChange",function(l){this._uiSetLastSortedBy(l.prevVal,l.newVal,k);});if(k.get("rendered")){k._uiSetColumnset(k.get("columnset"));this._uiSetLastSortedBy(null,this.get("lastSortedBy"),k);}},_setLastSortedBy:function(i){if(g.Lang.isString(i)){i={key:i,dir:"desc"};}if(i){return(i.dir==="desc")?{key:i.key,dir:"desc",notdir:"asc"}:{key:i.key,dir:"asc",notdir:"desc"};}else{return null;}},_uiSetLastSortedBy:function(n,m,l){var w=this.get("strings"),k=l.get("columnset"),x=n&&n.key,u=m&&m.key,i=n&&l.getClassName(n.dir),p=m&&l.getClassName(m.dir),r=k.keyHash[x],o=k.keyHash[u],q=l._tbodyNode,v=g.Lang.sub,j,t,s;if(r&&i){j=r.thNode;t=j.one("a");if(t){t.set("title",v(w.sortBy,{column:r.get("label")}));}j.removeClass(i);q.all("."+f(b,r.get("id"))).removeClass(i);}if(o&&p){j=o.thNode;t=j.one("a");if(t){s=(m.dir===d)?"reverseSortBy":"sortBy";t.set("title",v(w[s],{column:o.get("label")}));}j.addClass(p);q.all("."+f(b,o.get("id"))).addClass(p);}},_beforeCreateTheadThNode:function(k){var i,j;if(k.column.get("sortable")){i=this.get("lastSortedBy");j=(i&&i.dir===d&&i.key===k.column.get("key"))?"reverseSortBy":"sortBy";k.value=g.Lang.sub(this.get("template"),{link_class:k.link_class||"",link_title:g.Lang.sub(this.get("strings."+j),{column:k.column.get("label")}),link_href:"#",value:k.value});}},_beforeAttachTheadThNode:function(m){var l=this.get("lastSortedBy"),k=l&&l.key,i=l&&l.dir,j=l&&l.notdir;if(m.column.get("sortable")){m.th.addClass(f(h,"sortable"));}if(k&&(k===m.column.get("key"))){m.th.replaceClass(f(h,j),f(h,i));}},_beforeAttachTbodyTdNode:function(m){var l=this.get("lastSortedBy"),k=l&&l.key,i=l&&l.dir,j=l&&l.notdir;if(m.column.get("sortable")){m.td.addClass(f(h,"sortable"));}if(k&&(k===m.column.get("key"))){m.td.replaceClass(f(h,j),f(h,i));}},_onEventSortColumn:function(n){n.halt();var l=this.get("host"),k=l.get("columnset").idHash[n.currentTarget.get("id")],j,m,i,o,p;if(k.get("sortable")){j=k.get("key");m=k.get("field");i=this.get("lastSortedBy")||{};o=(i.key===j&&i.dir===d);p=k.get("sortFn");l.get("recordset").sort.sort(m,o,p);this.set("lastSortedBy",{key:j,dir:(o)?c:d});}}});g.namespace("Plugin").DataTableSort=e;},"3.7.3",{requires:["datatable-base-deprecated","plugin","recordset-sort"],lang:["en"]}); \ No newline at end of file
diff --git a/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated.js b/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated.js
new file mode 100644
index 000000000..573026b0b
--- /dev/null
+++ b/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-sort-deprecated",function(a){a.Intl.add("datatable-sort-deprecated","",{asc:"Ascending",desc:"Descending",sortBy:"Sort by {column}",reverseSortBy:"Reverse sort by {column}"});},"3.7.3"); \ No newline at end of file
diff --git a/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated_en.js b/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated_en.js
new file mode 100644
index 000000000..69d87762a
--- /dev/null
+++ b/js/yui3/datatable-sort-deprecated/lang/datatable-sort-deprecated_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-sort-deprecated_en",function(a){a.Intl.add("datatable-sort-deprecated","en",{asc:"Ascending",desc:"Descending",sortBy:"Sort by {column}",reverseSortBy:"Reverse sort by {column}"});},"3.7.3"); \ No newline at end of file
diff --git a/js/yui3/datatable-sort/assets/datatable-sort-core.css b/js/yui3/datatable-sort/assets/datatable-sort-core.css
new file mode 100644
index 000000000..c140327ed
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/datatable-sort-core.css
@@ -0,0 +1,15 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* foundational CSS */
+.yui3-datatable-sortable-column {
+ z-index: 1;
+}
+.yui3-datatable-sortable-column:focus,
+.yui3-datatable-sortable-column:active {
+ /* So the focus ring isn't masked by the surrounding elements */
+ z-index: 2;
+}
diff --git a/js/yui3/datatable-sort/assets/skins/night/datatable-sort.css b/js/yui3/datatable-sort/assets/skins/night/datatable-sort.css
new file mode 100644
index 000000000..de4cd7498
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/night/datatable-sort.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-sortable-column{z-index:1}.yui3-datatable-sortable-column:focus,.yui3-datatable-sortable-column:active{z-index:2}.yui3-skin-night .yui3-datatable-sortable-column{cursor:pointer}.yui3-skin-night .yui3-datatable-columns .yui3-datatable-sorted,.yui3-skin-night .yui3-datatable-sortable-column:hover{background-color:#4d4e4f;*background:#505152 url(../../../../assets/skins/night/sprite.png) repeat-x 0 -100px;background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(255,255,255,0.2)),color-stop(40%,rgba(255,255,255,0.1)),color-stop(80%,rgba(255,255,255,0.01)),to(transparent));background-image:-webkit-linear-gradient(rgba(255,255,255,0.2),rgba(255,255,255,0.1) 40%,rgba(255,255,255,0.01) 80%,transparent);background-image:-moz-linear-gradient(top,rgba(255,255,255,0.2),rgba(255,255,255,0.1) 40%,rgba(255,255,255,0.01) 80%,transparent);background-image:-ms-linear-gradient(rgba(255,255,255,0.2),rgba(255,255,255,0.1) 40%,rgba(255,255,255,0.01) 80%,transparent);background-image:-o-linear-gradient(rgba(255,255,255,0.2),rgba(255,255,255,0.1) 40%,rgba(255,255,255,0.01) 80%,transparent);background-image:linear-gradient(rgba(255,255,255,0.2),rgba(255,255,255,0.1) 40%,rgba(255,255,255,0.01) 80%,transparent)}.yui3-skin-night .yui3-datatable-sort-liner{display:block;height:100%;position:relative;padding-right:15px;position:relative}.yui3-skin-night .yui3-datatable-sort-indicator{position:absolute;right:0;bottom:.5ex;width:7px;height:10px;background:url(sort-arrow-sprite.png) no-repeat 0 0;_background:url(sort-arrow-sprite-ie.png) no-repeat 0 0;overflow:hidden}.yui3-skin-night .yui3-datatable-sorted .yui3-datatable-sort-indicator{background-position:0 -10px}.yui3-skin-night .yui3-datatable-sorted-desc .yui3-datatable-sort-indicator{background-position:0 -20px}.yui3-skin-night .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted{background-color:#262626;color:#b3b2b2}.yui3-skin-night .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted{background-color:#393a3a;color:#cbcbcb}#yui3-css-stamp.skin-night-datatable-sort{display:none}
diff --git a/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite-ie.png b/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite-ie.png
new file mode 100644
index 000000000..9ced28945
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite-ie.png
Binary files differ
diff --git a/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite.png b/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite.png
new file mode 100644
index 000000000..c4befbc9a
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/night/sort-arrow-sprite.png
Binary files differ
diff --git a/js/yui3/datatable-sort/assets/skins/sam/datatable-sort.css b/js/yui3/datatable-sort/assets/skins/sam/datatable-sort.css
new file mode 100644
index 000000000..86996b05f
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/sam/datatable-sort.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-datatable-sortable-column{z-index:1}.yui3-datatable-sortable-column:focus,.yui3-datatable-sortable-column:active{z-index:2}.yui3-skin-sam .yui3-datatable-sortable-column{cursor:pointer}.yui3-skin-sam .yui3-datatable-columns .yui3-datatable-sorted,.yui3-skin-sam .yui3-datatable-sortable-column:hover{*background:#c1c4c8 url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -100px;background-color:#f1f2f3}.yui3-skin-sam .yui3-datatable-sort-liner{display:block;height:100%;position:relative;padding-right:15px;position:relative}.yui3-skin-sam .yui3-datatable-sort-indicator{position:absolute;right:0;bottom:.5ex;width:7px;height:10px;background:url(sort-arrow-sprite.png) no-repeat 0 0;_background:url(sort-arrow-sprite-ie.png) no-repeat 0 0;overflow:hidden}.yui3-skin-sam .yui3-datatable-sorted .yui3-datatable-sort-indicator{background-position:0 -10px}.yui3-skin-sam .yui3-datatable-sorted-desc .yui3-datatable-sort-indicator{background-position:0 -20px}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted{background-color:#edf5ff}.yui3-skin-sam .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted{background-color:#dbeaff}#yui3-css-stamp.skin-sam-datatable-sort{display:none}
diff --git a/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite-ie.png b/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite-ie.png
new file mode 100644
index 000000000..f1f6576ab
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite-ie.png
Binary files differ
diff --git a/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite.png b/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite.png
new file mode 100644
index 000000000..47b8b1550
--- /dev/null
+++ b/js/yui3/datatable-sort/assets/skins/sam/sort-arrow-sprite.png
Binary files differ
diff --git a/js/yui3/datatable-sort/datatable-sort-min.js b/js/yui3/datatable-sort/datatable-sort-min.js
new file mode 100644
index 000000000..199c2587e
--- /dev/null
+++ b/js/yui3/datatable-sort/datatable-sort-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-sort",function(e,t){function l(){}var n=e.Lang,r=n.isBoolean,i=n.isString,s=n.isArray,o=n.isObject,u=e.Array,a=n.sub,f={asc:1,desc:-1,1:1,"-1":-1};l.ATTRS={sortable:{value:"auto",validator:"_validateSortable"},sortBy:{validator:"_validateSortBy",getter:"_getSortBy"},strings:{}},e.mix(l.prototype,{sort:function(t,n){return this.fire("sort",e.merge(n||{},{sortBy:t||this.get("sortBy")}))},SORTABLE_HEADER_TEMPLATE:'<div class="{className}" tabindex="0"><span class="{indicatorClass}"></span></div>',toggleSort:function(t,n){var r=this._sortBy,i=[],s,o,a,f,l;for(s=0,o=r.length;s<o;++s)f={},f[r[s]._id]=r[s].sortDir,i.push(f);if(t){t=u(t);for(s=0,o=t.length;s<o;++s){f=t[s],l=-1;for(a=i.length-1;s>=0;--s)if(i[a][f]){i[a][f]*=-1;break}}}else for(s=0,o=i.length;s<o;++s)for(f in i[s])if(i[s].hasOwnProperty(f)){i[s][f]*=-1;break}return this.fire("sort",e.merge(n||{},{sortBy:i}))},_afterSortByChange:function(e){this._setSortBy(),this._sortBy.length&&(this.data.comparator||(this.data.comparator=this._sortComparator),this.data.sort())},_afterSortDataChange:function(e){(e.prevVal!==e.newVal||e.newVal.hasOwnProperty("_compare"))&&this._initSortFn()},_afterSortRecordChange:function(e){var t,n;for(t=0,n=this._sortBy.length;t<n;++t)if(e.changed[this._sortBy[t].key]){this.data.sort();break}},_bindSortUI:function(){var t=this._eventHandles;t.sortAttrs||(t.sortAttrs=this.after(["sortableChange","sortByChange","columnsChange"],e.bind("_uiSetSortable",this))),!t.sortUITrigger&&this._theadNode&&(t.sortUITrigger=this.delegate(["click","keydown"],e.rbind("_onUITriggerSort",this),"."+this.getClassName("sortable","column")))},_defSortFn:function(e){this.set.apply(this,["sortBy",e.sortBy].concat(e.details))},_getSortBy:function(e,t){var n,r,i,s;t=t.slice(7);if(t==="state"){n=[];for(r=0,i=this._sortBy.length;r<i;++r)s=this._sortBy[r],n.push({column:s._id,dir:s.sortDir});return{state:n.length===1?n[0]:n}}return e},initializer:function(){var t=e.bind("_parseSortable",this);this._parseSortable(),this._setSortBy(),this._initSortFn(),this._initSortStrings(),this.after({"table:renderHeader":e.bind("_renderSortable",this),dataChange:e.bind("_afterSortDataChange",this),sortByChange:e.bind("_afterSortByChange",this),sortableChange:t,columnsChange:t}),this.data.after(this.data.model.NAME+":change",e.bind("_afterSortRecordChange",this)),this.publish("sort",{defaultFn:e.bind("_defSortFn",this)})},_initSortFn:function(){var e=this;this.data._compare=function(t,n){var r=0,i,s,o,u,a,f;for(i=0,s=e._sortBy.length;!r&&i<s;++i)o=e._sortBy[i],u=o.sortDir,o.sortFn?r=o.sortFn(t,n,u===-1):(a=t.get(o.key)||"",f=n.get(o.key)||"",r=a>f?u:a<f?-u:0);return r},this._sortBy.length?(this.data.comparator=this._sortComparator,this.data.sort()):delete this.data.comparator},_initSortStrings:function(){this.set("strings",e.mix(this.get("strings")||{},e.Intl.get("datatable-sort")))},_onUITriggerSort:function(e){var t=e.currentTarget.getAttribute("data-yui3-col-id"),n=e.shiftKey?this.get("sortBy"):[{}],r=t&&this.getColumn(t),i,s;if(e.type==="keydown"&&e.keyCode!==32)return;e.preventDefault();if(r){if(e.shiftKey){for(i=0,s=n.length;i<s;++i)if(t===n[i]||Math.abs(n[i][t]===1)){o(n[i])||(n[i]={}),n[i][t]=-(r.sortDir|0)||1;break}i>=s&&n.push(r._id)}else n[0][t]=-(r.sortDir|0)||1;this.fire("sort",{originEvent:e,sortBy:n})}},_parseSortable:function(){var e=this.get("sortable"),t=[],n,r,i;if(s(e))for(n=0,r=e.length;n<r;++n){i=e[n];if(!o(i,!0)||s(i))i=this.getColumn(i);i&&t.push(i)}else if(e){t=this._displayColumns.slice();if(e==="auto")for(n=t.length-1;n>=0;--n)t[n].sortable||t.splice(n,1)}this._sortable=t},_renderSortable:function(){this._uiSetSortable(),this._bindSortUI()},_setSortBy:function(){var e=this._displayColumns,t=this.get("sortBy")||[],n=" "+this.getClassName("sorted"),r,i,s,a,l,c;this._sortBy=[];for(r=0,i=e.length;r<i;++r)c=e[r],delete c.sortDir,c.className&&(c.className=c.className.replace(n,""));t=u(t);for(r=0,i=t.length;r<i;++r){s=t[r],a=1;if(o(s)){l=s;for(s in l)if(l.hasOwnProperty(s)){a=f[l[s]];break}}s&&(c=this.getColumn(s)||{_id:s,key:s},c&&(c.sortDir=a,c.className||(c.className=""),c.className+=n,this._sortBy.push(c)))}},_sortComparator:function(e){return e},_uiSetSortable:function(){var t=this._sortable||[],n=this.getClassName("sortable","column"),r=this.getClassName("sorted"),i=this.getClassName("sorted","desc"),s=this.getClassName("sort","liner"),o=this.getClassName("sort","indicator"),u={},f,l,c,h,p,d,v;this.get("boundingBox").toggleClass(this.getClassName("sortable"),t.length);for(f=0,l=t.length;f<l;++f)u[t[f].id]=t[f];this._theadNode.all("."+n).each(function(e){var t=u[e.get("id")],a=e.one("."+s),f;t?t.sortDir||e.removeClass(r).removeClass(i):(e.removeClass(n).removeClass(r).removeClass(i),a&&a.replace(a.get("childNodes").toFrag()),f=e.one("."+o),f&&f.remove().destroy(!0))});for(f=0,l=t.length;f<l;++f)c=t[f],h=this._theadNode.one("#"+c.id),v=c.sortDir===-1,h&&(p=h.one("."+s),h.addClass(n),c.sortDir&&(h.addClass(r),h.toggleClass(i,v),h.setAttribute("aria-sort",v?"descending":"ascending")),p||(p=e.Node.create(e.Lang.sub(this.SORTABLE_HEADER_TEMPLATE,{className:s,indicatorClass:o})),p.prepend(h.get("childNodes").toFrag()),h.append(p)),d=a(this.getString(c.sortDir===1?"reverseSortBy":"sortBy"),{column:c.abbr||c.label||c.key||"column "+f}),h.setAttribute("title",d),h.setAttribute("aria-labelledby",c.id))},_validateSortable:function(e){return e==="auto"||r(e)||s(e)},_validateSortBy:function(e){return e===null||i(e)||o(e,!0)||s(e)&&(i(e[0])||o(e,!0))}},!0),e.DataTable.Sortable=l,e.Base.mix(e.DataTable,[l])},"3.7.3",{requires:["datatable-base"],lang:["en"],skinnable:!0});
diff --git a/js/yui3/datatable-sort/lang/datatable-sort.js b/js/yui3/datatable-sort/lang/datatable-sort.js
new file mode 100644
index 000000000..2ac00cc7f
--- /dev/null
+++ b/js/yui3/datatable-sort/lang/datatable-sort.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-sort",function(e){e.Intl.add("datatable-sort","",{asc:"Ascending",desc:"Descending",sortBy:"Sort by {column}",reverseSortBy:"Reverse sort by {column}"})},"3.7.3");
diff --git a/js/yui3/datatable-sort/lang/datatable-sort_en.js b/js/yui3/datatable-sort/lang/datatable-sort_en.js
new file mode 100644
index 000000000..bbbf540ac
--- /dev/null
+++ b/js/yui3/datatable-sort/lang/datatable-sort_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatable-sort_en",function(e){e.Intl.add("datatable-sort","en",{asc:"Ascending",desc:"Descending",sortBy:"Sort by {column}",reverseSortBy:"Reverse sort by {column}"})},"3.7.3");
diff --git a/js/yui3/datatable-table/datatable-table-min.js b/js/yui3/datatable-table/datatable-table-min.js
new file mode 100644
index 000000000..d0acbd1d0
--- /dev/null
+++ b/js/yui3/datatable-table/datatable-table-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatable-table",function(e,t){var n=e.Array,r=e.Lang,i=r.sub,s=r.isArray,o=r.isFunction;e.namespace("DataTable").TableView=e.Base.create("table",e.View,[],{CAPTION_TEMPLATE:'<caption class="{className}"/>',TABLE_TEMPLATE:'<table cellspacing="0" class="{className}"/>',getCell:function(e,t){return this.body&&this.body.getCell&&this.body.getCell.apply(this.body,arguments)},getClassName:function(){var t=this.host,r=t&&t.constructor.NAME||this.constructor.NAME;return t&&t.getClassName?t.getClassName.apply(t,arguments):e.ClassNameManager.getClassName.apply(e.ClassNameManager,[r].concat(n(arguments,0,!0)))},getRecord:function(){return this.body&&this.body.getRecord&&this.body.getRecord.apply(this.body,arguments)},getRow:function(e){return this.body&&this.body.getRow&&this.body.getRow.apply(this.body,arguments)},_afterSummaryChange:function(e){this._uiSetSummary(e.newVal)},_afterCaptionChange:function(e){this._uiSetCaption(e.newVal)},_afterWidthChange:function(e){this._uiSetWidth(e.newVal)},_bindUI:function(){var t;this._eventHandles||(t=e.bind("_relayAttrChange",this),this._eventHandles=this.after({columnsChange:t,modelListChange:t,summaryChange:e.bind("_afterSummaryChange",this),captionChange:e.bind("_afterCaptionChange",this),widthChange:e.bind("_afterWidthChange",this)}))},_createTable:function(){return e.Node.create(i(this.TABLE_TEMPLATE,{className:this.getClassName("table")})).empty()},_defRenderBodyFn:function(e){e.view.render()},_defRenderFooterFn:function(e){e.view.render()},_defRenderHeaderFn:function(e){e.view.render()},_defRenderTableFn:function(t){var n=this.get("container"),r=this.getAttrs();this.tableNode||(this.tableNode=this._createTable()),r.host=this.get("host")||this,r.table=this,r.container=this.tableNode,this._uiSetCaption(this.get("caption")),this._uiSetSummary(this.get("summary")),this._uiSetWidth(this.get("width"));if(this.head||t.headerView)this.head||(this.head=new t.headerView(e.merge(r,t.headerConfig))),this.fire("renderHeader",{view:this.head});if(this.foot||t.footerView)this.foot||(this.foot=new t.footerView(e.merge(r,t.footerConfig))),this.fire("renderFooter",{view:this.foot});r.columns=this.displayColumns;if(this.body||t.bodyView)this.body||(this.body=new t.bodyView(e.merge(r,t.bodyConfig))),this.fire("renderBody",{view:this.body});n.contains(this.tableNode)||n.append(this.tableNode),this._bindUI()},destructor:function(){this.head&&this.head.destroy&&this.head.destroy(),delete this.head,this.foot&&this.foot.destroy&&this.foot.destroy(),delete this.foot,this.body&&this.body.destroy&&this.body.destroy(),delete this.body,this._eventHandles&&(this._eventHandles.detach(),delete this._eventHandles),this.tableNode&&this.tableNode.remove().destroy(!0)},_extractDisplayColumns:function(){function n(e){var r,i,o;for(r=0,i=e.length;r<i;++r)o=e[r],s(o.children)?n(o.children):t.push(o)}var e=this.get("columns"),t=[];n(e),this.displayColumns=t},_initEvents:function(){this.publish({renderTable:{defaultFn:e.bind("_defRenderTableFn",this)},renderHeader:{defaultFn:e.bind("_defRenderHeaderFn",this)},renderBody:{defaultFn:e.bind("_defRenderBodyFn",this)},renderFooter:{defaultFn:e.bind("_defRenderFooterFn",this)}})},initializer:function(e){this.host=e.host,this._initEvents(),this._extractDisplayColumns(),this.after("columnsChange",this._extractDisplayColumns,this)},_relayAttrChange:function(e){var t=e.attrName,n=e.newVal;this.head&&this.head.set(t,n),this.foot&&this.foot.set(t,n),this.body&&(t==="columns"&&(n=this.displayColumns),this.body.set(t,n))},render:function(){return this.get("container")&&this.fire("renderTable",{headerView:this.get("headerView"),headerConfig:this.get("headerConfig"),bodyView:this.get("bodyView"),bodyConfig:this.get("bodyConfig"),footerView:this.get("footerView"),footerConfig:this.get("footerConfig")}),this},_uiSetCaption:function(t){var n=this.tableNode,r=this.captionNode;t?(r||(this.captionNode=r=e.Node.create(i(this.CAPTION_TEMPLATE,{className:this.getClassName("caption")})),n.prepend(this.captionNode)),r.setHTML(t)):r&&(r.remove(!0),delete this.captionNode)},_uiSetSummary:function(e){e?this.tableNode.setAttribute("summary",e):this.tableNode.removeAttribute("summary")},_uiSetWidth:function(e){var t=this.tableNode;t.setStyle("width",e?this.get("container").get("offsetWidth")-(parseInt(t.getComputedStyle("borderLeftWidth"),10)|0)-(parseInt(t.getComputedStyle("borderLeftWidth"),10)|0)+"px":""),t.setStyle("width",e)},_validateView:function(e){return o(e)&&e.prototype.render}},{ATTRS:{columns:{validator:s},width:{value:"",validator:r.isString},headerView:{value:e.DataTable.HeaderView,validator:"_validateView"},footerView:{validator:"_validateView"},bodyView:{value:e.DataTable.BodyView,validator:"_validateView"}}})},"3.7.3",{requires:["datatable-core","datatable-head","datatable-body","view","classnamemanager"]});
diff --git a/js/yui3/datatype-date-format/datatype-date-format-min.js b/js/yui3/datatype-date-format/datatype-date-format-min.js
new file mode 100644
index 000000000..b3540934f
--- /dev/null
+++ b/js/yui3/datatype-date-format/datatype-date-format-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-date-format",function(e,t){var n=function(e,t,n){typeof n=="undefined"&&(n=10),t+="";for(;parseInt(e,10)<n&&n>1;n/=10)e=t+e;return e.toString()},r={formats:{a:function(e,t){return t.a[e.getDay()]},A:function(e,t){return t.A[e.getDay()]},b:function(e,t){return t.b[e.getMonth()]},B:function(e,t){return t.B[e.getMonth()]},C:function(e){return n(parseInt(e.getFullYear()/100,10),0)},d:["getDate","0"],e:["getDate"," "],g:function(e){return n(parseInt(r.formats.G(e)%100,10),0)},G:function(e){var t=e.getFullYear(),n=parseInt(r.formats.V(e),10),i=parseInt(r.formats.W(e),10);return i>n?t++:i===0&&n>=52&&t--,t},H:["getHours","0"],I:function(e){var t=e.getHours()%12;return n(t===0?12:t,0)},j:function(e){var t=new Date(""+e.getFullYear()+"/1/1 GMT"),r=new Date(""+e.getFullYear()+"/"+(e.getMonth()+1)+"/"+e.getDate()+" GMT"),i=r-t,s=parseInt(i/6e4/60/24,10)+1;return n(s,0,100)},k:["getHours"," "],l:function(e){var t=e.getHours()%12;return n(t===0?12:t," ")},m:function(e){return n(e.getMonth()+1,0)},M:["getMinutes","0"],p:function(e,t){return t.p[e.getHours()>=12?1:0]},P:function(e,t){return t.P[e.getHours()>=12?1:0]},s:function(e,t){return parseInt(e.getTime()/1e3,10)},S:["getSeconds","0"],u:function(e){var t=e.getDay();return t===0?7:t},U:function(e){var t=parseInt(r.formats.j(e),10),i=6-e.getDay(),s=parseInt((t+i)/7,10);return n(s,0)},V:function(e){var t=parseInt(r.formats.W(e),10),i=(new Date(""+e.getFullYear()+"/1/1")).getDay(),s=t+(i>4||i<=1?0:1);return s===53&&(new Date(""+e.getFullYear()+"/12/31")).getDay()<4?s=1:s===0&&(s=r.formats.V(new Date(""+(e.getFullYear()-1)+"/12/31"))),n(s,0)},w:"getDay",W:function(e){var t=parseInt(r.formats.j(e),10),i=7-r.formats.u(e),s=parseInt((t+i)/7,10);return n(s,0,10)},y:function(e){return n(e.getFullYear()%100,0)},Y:"getFullYear",z:function(e){var t=e.getTimezoneOffset(),r=n(parseInt(Math.abs(t/60),10),0),i=n(Math.abs(t%60),0);return(t>0?"-":"+")+r+i},Z:function(e){var t=e.toString().replace(/^.*:\d\d( GMT[+-]\d+)? \(?([A-Za-z ]+)\)?\d*$/,"$2").replace(/[a-z ]/g,"");return t.length>4&&(t=r.formats.z(e)),t},"%":function(e){return"%"}},aggregates:{c:"locale",D:"%m/%d/%y",F:"%Y-%m-%d",h:"%b",n:"\n",r:"%I:%M:%S %p",R:"%H:%M",t:" ",T:"%H:%M:%S",x:"locale",X:"locale"},format:function(t,i){i=i||{};if(!e.Lang.isDate(t))return e.Lang.isValue(t)?t:"";var s,o,u,a,f;s=i.format||"%Y-%m-%d",o=e.Intl.get("datatype-date-format");var l=function(e,t){if(u&&t==="r")return o[t];var n=r.aggregates[t];return n==="locale"?o[t]:n},c=function(i,s){var u=r.formats[s];switch(e.Lang.type(u)){case"string":return t[u]();case"function":return u.call(t,t,o);case"array":if(e.Lang.type(u[0])==="string")return n(t[u[0]](),u[1]);default:return s}};while(s.match(/%[cDFhnrRtTxX]/))s=s.replace(/%([cDFhnrRtTxX])/g,l);var h=s.replace(/%([aAbBCdegGHIjklmMpPsSuUVwWyYzZ%])/g,c);return l=c=undefined,h}};e.mix(e.namespace("Date"),r),e.namespace("DataType"),e.DataType.Date=e.Date},"3.7.3",{lang:["ar","ar-JO","ca","ca-ES","da","da-DK","de","de-AT","de-DE","el","el-GR","en","en-AU","en-CA","en-GB","en-IE","en-IN","en-JO","en-MY","en-NZ","en-PH","en-SG","en-US","es","es-AR","es-BO","es-CL","es-CO","es-EC","es-ES","es-MX","es-PE","es-PY","es-US","es-UY","es-VE","fi","fi-FI","fr","fr-BE","fr-CA","fr-FR","hi","hi-IN","id","id-ID","it","it-IT","ja","ja-JP","ko","ko-KR","ms","ms-MY","nb","nb-NO","nl","nl-BE","nl-NL","pl","pl-PL","pt","pt-BR","ro","ro-RO","ru","ru-RU","sv","sv-SE","th","th-TH","tr","tr-TR","vi","vi-VN","zh-Hans","zh-Hans-CN","zh-Hant","zh-Hant-HK","zh-Hant-TW"]});
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format.js b/js/yui3/datatype-date-format/lang/datatype-date-format.js
new file mode 100644
index 000000000..957f6c9f3
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format",function(e){e.Intl.add("datatype-date-format","",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%Y-%m-%dT%H:%M:%S%z",p:["AM","PM"],P:["am","pm"],x:"%Y-%m-%d",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ar-JO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ar-JO.js
new file mode 100644
index 000000000..1b2b3a260
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ar-JO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ar-JO",function(e){e.Intl.add("datatype-date-format","ar-JO",{a:["\u0627\u0644\u0623\u062d\u062f","\u0627\u0644\u0627\u062b\u0646\u064a\u0646","\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621","\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621","\u0627\u0644\u062e\u0645\u064a\u0633","\u0627\u0644\u062c\u0645\u0639\u0629","\u0627\u0644\u0633\u0628\u062a"],A:["\u0627\u0644\u0623\u062d\u062f","\u0627\u0644\u0625\u062b\u0646\u064a\u0646","\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621","\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621","\u0627\u0644\u062e\u0645\u064a\u0633","\u0627\u0644\u062c\u0645\u0639\u0629","\u0627\u0644\u0633\u0628\u062a"],b:["\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a","\u0634\u0628\u0627\u0637","\u0622\u0630\u0627\u0631","\u0646\u064a\u0633\u0627\u0646","\u0623\u064a\u0627\u0631","\u062d\u0632\u064a\u0631\u0627\u0646","\u062a\u0645\u0648\u0632","\u0622\u0628","\u0623\u064a\u0644\u0648\u0644","\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644","\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a","\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"],B:["\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a","\u0634\u0628\u0627\u0637","\u0622\u0630\u0627\u0631","\u0646\u064a\u0633\u0627\u0646","\u0623\u064a\u0627\u0631","\u062d\u0632\u064a\u0631\u0627\u0646","\u062a\u0645\u0648\u0632","\u0622\u0628","\u0623\u064a\u0644\u0648\u0644","\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644","\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a","\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"],c:"%a\u060c %d %B %Y %Z %l:%M:%S %p",p:["\u0635","\u0645"],P:["\u0635","\u0645"],x:"%d\u200f/%m\u200f/%Y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ar.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ar.js
new file mode 100644
index 000000000..65183c71f
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ar.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ar",function(e){e.Intl.add("datatype-date-format","ar",{a:["\u0623\u062d\u062f","\u0625\u062b\u0646\u064a\u0646","\u062b\u0644\u0627\u062b\u0627\u0621","\u0623\u0631\u0628\u0639\u0627\u0621","\u062e\u0645\u064a\u0633","\u062c\u0645\u0639\u0629","\u0633\u0628\u062a"],A:["\u0627\u0644\u0623\u062d\u062f","\u0627\u0644\u0625\u062b\u0646\u064a\u0646","\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621","\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621","\u0627\u0644\u062e\u0645\u064a\u0633","\u0627\u0644\u062c\u0645\u0639\u0629","\u0627\u0644\u0633\u0628\u062a"],b:["\u064a\u0646\u0627\u064a\u0631","\u0641\u0628\u0631\u0627\u064a\u0631","\u0645\u0627\u0631\u0633","\u0623\u0628\u0631\u064a\u0644","\u0645\u0627\u064a\u0648","\u064a\u0648\u0646\u064a\u0648","\u064a\u0648\u0644\u064a\u0648","\u0623\u063a\u0633\u0637\u0633","\u0633\u0628\u062a\u0645\u0628\u0631","\u0623\u0643\u062a\u0648\u0628\u0631","\u0646\u0648\u0641\u0645\u0628\u0631","\u062f\u064a\u0633\u0645\u0628\u0631"],B:["\u064a\u0646\u0627\u064a\u0631","\u0641\u0628\u0631\u0627\u064a\u0631","\u0645\u0627\u0631\u0633","\u0623\u0628\u0631\u064a\u0644","\u0645\u0627\u064a\u0648","\u064a\u0648\u0646\u064a\u0648","\u064a\u0648\u0644\u064a\u0648","\u0623\u063a\u0633\u0637\u0633","\u0633\u0628\u062a\u0645\u0628\u0631","\u0623\u0643\u062a\u0648\u0628\u0631","\u0646\u0648\u0641\u0645\u0628\u0631","\u062f\u064a\u0633\u0645\u0628\u0631"],c:"%a\u060c %d %B %Y %Z %l:%M:%S %p",p:["\u0635","\u0645"],P:["\u0635","\u0645"],x:"%d\u200f/%m\u200f/%Y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ca-ES.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ca-ES.js
new file mode 100644
index 000000000..5003029c9
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ca-ES.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ca-ES",function(e){e.Intl.add("datatype-date-format","ca-ES",{a:["dg.","dl.","dt.","dc.","dj.","dv.","ds."],A:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],b:["gen.","febr.","mar\u00e7","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],B:["gener","febrer","mar\u00e7","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],c:"%a %d %b %Y %k:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%k:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ca.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ca.js
new file mode 100644
index 000000000..0678faf61
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ca.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ca",function(e){e.Intl.add("datatype-date-format","ca",{a:["dg.","dl.","dt.","dc.","dj.","dv.","ds."],A:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],b:["gen.","febr.","mar\u00e7","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],B:["gener","febrer","mar\u00e7","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],c:"%a %d %b %Y %k:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%k:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_da-DK.js b/js/yui3/datatype-date-format/lang/datatype-date-format_da-DK.js
new file mode 100644
index 000000000..c4a0acab0
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_da-DK.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_da-DK",function(e){e.Intl.add("datatype-date-format","da-DK",{a:["s\u00f8n","man","tir","ons","tor","fre","l\u00f8r"],A:["s\u00f8ndag","mandag","tirsdag","onsdag","torsdag","fredag","l\u00f8rdag"],b:["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],B:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],c:"%a. %d. %b %Y %H.%M.%S %Z",p:["F.M.","E.M."],P:["f.m.","e.m."],x:"%d/%m/%y",X:"%H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_da.js b/js/yui3/datatype-date-format/lang/datatype-date-format_da.js
new file mode 100644
index 000000000..75f92e20d
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_da.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_da",function(e){e.Intl.add("datatype-date-format","da",{a:["s\u00f8n","man","tir","ons","tor","fre","l\u00f8r"],A:["s\u00f8ndag","mandag","tirsdag","onsdag","torsdag","fredag","l\u00f8rdag"],b:["jan.","feb.","mar.","apr.","maj","jun.","jul.","aug.","sep.","okt.","nov.","dec."],B:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],c:"%a. %d. %b %Y %H.%M.%S %Z",p:["F.M.","E.M."],P:["f.m.","e.m."],x:"%d/%m/%y",X:"%H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_de-AT.js b/js/yui3/datatype-date-format/lang/datatype-date-format_de-AT.js
new file mode 100644
index 000000000..143539b8b
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_de-AT.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_de-AT",function(e){e.Intl.add("datatype-date-format","de-AT",{a:["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],A:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],b:["J\u00e4n","Feb","M\u00e4r","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],B:["J\u00e4nner","Februar","M\u00e4rz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],c:"%a, %d. %b %Y %H:%M:%S %Z",p:["VORM.","NACHM."],P:["vorm.","nachm."],x:"%d.%m.%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_de-DE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_de-DE.js
new file mode 100644
index 000000000..f8ab100a5
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_de-DE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_de-DE",function(e){e.Intl.add("datatype-date-format","de-DE",{a:["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],A:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],b:["Jan","Feb","M\u00e4r","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],B:["Januar","Februar","M\u00e4rz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],c:"%a, %d. %b %Y %H:%M:%S %Z",p:["VORM.","NACHM."],P:["vorm.","nachm."],x:"%d.%m.%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_de.js b/js/yui3/datatype-date-format/lang/datatype-date-format_de.js
new file mode 100644
index 000000000..59e6d1b4f
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_de.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_de",function(e){e.Intl.add("datatype-date-format","de",{a:["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],A:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],b:["Jan","Feb","M\u00e4r","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],B:["Januar","Februar","M\u00e4rz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],c:"%a, %d. %b %Y %H:%M:%S %Z",p:["VORM.","NACHM."],P:["vorm.","nachm."],x:"%d.%m.%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_el-GR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_el-GR.js
new file mode 100644
index 000000000..61ae9b0a9
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_el-GR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_el-GR",function(e){e.Intl.add("datatype-date-format","el-GR",{a:["\u039a\u03c5\u03c1","\u0394\u03b5\u03c5","\u03a4\u03c1\u03b9","\u03a4\u03b5\u03c4","\u03a0\u03b5\u03bc","\u03a0\u03b1\u03c1","\u03a3\u03b1\u03b2"],A:["\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae","\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1","\u03a4\u03c1\u03af\u03c4\u03b7","\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7","\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7","\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae","\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"],b:["\u0399\u03b1\u03bd","\u03a6\u03b5\u03b2","\u039c\u03b1\u03c1","\u0391\u03c0\u03c1","\u039c\u03b1\u03ca","\u0399\u03bf\u03c5\u03bd","\u0399\u03bf\u03c5\u03bb","\u0391\u03c5\u03b3","\u03a3\u03b5\u03c0","\u039f\u03ba\u03c4","\u039d\u03bf\u03b5","\u0394\u03b5\u03ba"],B:["\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5","\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5","\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5","\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5","\u039c\u03b1\u0390\u03bf\u03c5","\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5","\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5","\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5","\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5","\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5","\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5","\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5"],c:"%a, %d %b %Y %l:%M:%S %p %Z",p:["\u03a0.\u039c.","\u039c.\u039c."],P:["\u03c0.\u03bc.","\u03bc.\u03bc."],x:"%d/%m/%Y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_el.js b/js/yui3/datatype-date-format/lang/datatype-date-format_el.js
new file mode 100644
index 000000000..fca7aed62
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_el.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_el",function(e){e.Intl.add("datatype-date-format","el",{a:["\u039a\u03c5\u03c1","\u0394\u03b5\u03c5","\u03a4\u03c1\u03b9","\u03a4\u03b5\u03c4","\u03a0\u03b5\u03bc","\u03a0\u03b1\u03c1","\u03a3\u03b1\u03b2"],A:["\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae","\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1","\u03a4\u03c1\u03af\u03c4\u03b7","\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7","\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7","\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae","\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"],b:["\u0399\u03b1\u03bd","\u03a6\u03b5\u03b2","\u039c\u03b1\u03c1","\u0391\u03c0\u03c1","\u039c\u03b1\u03ca","\u0399\u03bf\u03c5\u03bd","\u0399\u03bf\u03c5\u03bb","\u0391\u03c5\u03b3","\u03a3\u03b5\u03c0","\u039f\u03ba\u03c4","\u039d\u03bf\u03b5","\u0394\u03b5\u03ba"],B:["\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5","\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5","\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5","\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5","\u039c\u03b1\u0390\u03bf\u03c5","\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5","\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5","\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5","\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5","\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5","\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5","\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5"],c:"%a, %d %b %Y %l:%M:%S %p %Z",p:["\u03a0.\u039c.","\u039c.\u039c."],P:["\u03c0.\u03bc.","\u03bc.\u03bc."],x:"%d/%m/%Y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-AU.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-AU.js
new file mode 100644
index 000000000..819516ad0
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-AU.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-AU",function(e){e.Intl.add("datatype-date-format","en-AU",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-CA.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-CA.js
new file mode 100644
index 000000000..df90c9e46
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-CA.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-CA",function(e){e.Intl.add("datatype-date-format","en-CA",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%y-%m-%d",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-GB.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-GB.js
new file mode 100644
index 000000000..cbd93ee39
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-GB.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-GB",function(e){e.Intl.add("datatype-date-format","en-GB",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-IE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-IE.js
new file mode 100644
index 000000000..9bcf729dc
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-IE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-IE",function(e){e.Intl.add("datatype-date-format","en-IE",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-IN.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-IN.js
new file mode 100644
index 000000000..79beebd0d
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-IN.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-IN",function(e){e.Intl.add("datatype-date-format","en-IN",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-JO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-JO.js
new file mode 100644
index 000000000..e7b8fa01a
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-JO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-JO",function(e){e.Intl.add("datatype-date-format","en-JO",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-MY.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-MY.js
new file mode 100644
index 000000000..2450fb625
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-MY.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-MY",function(e){e.Intl.add("datatype-date-format","en-MY",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-NZ.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-NZ.js
new file mode 100644
index 000000000..b1ae99a8b
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-NZ.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-NZ",function(e){e.Intl.add("datatype-date-format","en-NZ",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-PH.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-PH.js
new file mode 100644
index 000000000..39d37a08f
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-PH.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-PH",function(e){e.Intl.add("datatype-date-format","en-PH",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-SG.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-SG.js
new file mode 100644
index 000000000..1e394f2f6
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-SG.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-SG",function(e){e.Intl.add("datatype-date-format","en-SG",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en-US.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en-US.js
new file mode 100644
index 000000000..9afb7daa6
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en-US.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en-US",function(e){e.Intl.add("datatype-date-format","en-US",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_en.js b/js/yui3/datatype-date-format/lang/datatype-date-format_en.js
new file mode 100644
index 000000000..62518c89b
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_en",function(e){e.Intl.add("datatype-date-format","en",{a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a, %b %d, %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-AR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-AR.js
new file mode 100644
index 000000000..dc9a5ac18
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-AR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-AR",function(e){e.Intl.add("datatype-date-format","es-AR",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %Hh'%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%Hh'%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-BO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-BO.js
new file mode 100644
index 000000000..eb3d92760
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-BO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-BO",function(e){e.Intl.add("datatype-date-format","es-BO",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-CL.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-CL.js
new file mode 100644
index 000000000..4effb79ad
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-CL.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-CL",function(e){e.Intl.add("datatype-date-format","es-CL",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d-%m-%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-CO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-CO.js
new file mode 100644
index 000000000..dc0873553
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-CO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-CO",function(e){e.Intl.add("datatype-date-format","es-CO",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-EC.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-EC.js
new file mode 100644
index 000000000..b6551318d
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-EC.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-EC",function(e){e.Intl.add("datatype-date-format","es-EC",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-ES.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-ES.js
new file mode 100644
index 000000000..988b2146c
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-ES.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-ES",function(e){e.Intl.add("datatype-date-format","es-ES",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-MX.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-MX.js
new file mode 100644
index 000000000..2466e60ed
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-MX.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-MX",function(e){e.Intl.add("datatype-date-format","es-MX",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-PE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-PE.js
new file mode 100644
index 000000000..b6c10ea79
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-PE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-PE",function(e){e.Intl.add("datatype-date-format","es-PE",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %HH%M'%S\" %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%HH%M'%S\""})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-PY.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-PY.js
new file mode 100644
index 000000000..7e9289314
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-PY.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-PY",function(e){e.Intl.add("datatype-date-format","es-PY",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-US.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-US.js
new file mode 100644
index 000000000..3469a46cb
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-US.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-US",function(e){e.Intl.add("datatype-date-format","es-US",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %l:%M:%S %p %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%m/%d/%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-UY.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-UY.js
new file mode 100644
index 000000000..9d3d1851f
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-UY.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-UY",function(e){e.Intl.add("datatype-date-format","es-UY",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es-VE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es-VE.js
new file mode 100644
index 000000000..ad57e9f2e
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es-VE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es-VE",function(e){e.Intl.add("datatype-date-format","es-VE",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_es.js b/js/yui3/datatype-date-format/lang/datatype-date-format_es.js
new file mode 100644
index 000000000..cbd9cd7d7
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_es.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_es",function(e){e.Intl.add("datatype-date-format","es",{a:["dom","lun","mar","mi\u00e9","jue","vie","s\u00e1b"],A:["domingo","lunes","martes","mi\u00e9rcoles","jueves","viernes","s\u00e1bado"],b:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],B:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["A.M.","P.M."],P:["a.m.","p.m."],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fi-FI.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fi-FI.js
new file mode 100644
index 000000000..57d83071c
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fi-FI.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fi-FI",function(e){e.Intl.add("datatype-date-format","fi-FI",{a:["su","ma","ti","ke","to","pe","la"],A:["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],b:["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kes\u00e4kuuta","hein\u00e4kuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],B:["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kes\u00e4kuuta","hein\u00e4kuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],c:"%a %d. %b %Y %k.%M.%S %Z",p:["AP.","IP."],P:["ap.","ip."],x:"%d.%m.%Y",X:"%k.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fi.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fi.js
new file mode 100644
index 000000000..81e47f182
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fi.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fi",function(e){e.Intl.add("datatype-date-format","fi",{a:["su","ma","ti","ke","to","pe","la"],A:["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],b:["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kes\u00e4kuuta","hein\u00e4kuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],B:["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kes\u00e4kuuta","hein\u00e4kuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],c:"%a %d. %b %Y %k.%M.%S %Z",p:["AP.","IP."],P:["ap.","ip."],x:"%d.%m.%Y",X:"%k.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fr-BE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-BE.js
new file mode 100644
index 000000000..1e698ad34
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-BE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fr-BE",function(e){e.Intl.add("datatype-date-format","fr-BE",{a:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],A:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],b:["janv.","f\u00e9vr.","mars","avr.","mai","juin","juil.","ao\u00fbt","sept.","oct.","nov.","d\u00e9c."],B:["janvier","f\u00e9vrier","mars","avril","mai","juin","juillet","ao\u00fbt","septembre","octobre","novembre","d\u00e9cembre"],c:"%a %d %b %Y %k h %M min %S s %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%k h %M min %S s"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fr-CA.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-CA.js
new file mode 100644
index 000000000..fd2378127
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-CA.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fr-CA",function(e){e.Intl.add("datatype-date-format","fr-CA",{a:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],A:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],b:["janv.","f\u00e9vr.","mars","avr.","mai","juin","juil.","ao\u00fbt","sept.","oct.","nov.","d\u00e9c."],B:["janvier","f\u00e9vrier","mars","avril","mai","juin","juillet","ao\u00fbt","septembre","octobre","novembre","d\u00e9cembre"],c:"%a %d %b %Y %H h %M min %S s %Z",p:["AM","PM"],P:["am","pm"],x:"%y-%m-%d",X:"%H h %M min %S s"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fr-FR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-FR.js
new file mode 100644
index 000000000..c347b6b28
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fr-FR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fr-FR",function(e){e.Intl.add("datatype-date-format","fr-FR",{a:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],A:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],b:["janv.","f\u00e9vr.","mars","avr.","mai","juin","juil.","ao\u00fbt","sept.","oct.","nov.","d\u00e9c."],B:["janvier","f\u00e9vrier","mars","avril","mai","juin","juillet","ao\u00fbt","septembre","octobre","novembre","d\u00e9cembre"],c:"%a %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_fr.js b/js/yui3/datatype-date-format/lang/datatype-date-format_fr.js
new file mode 100644
index 000000000..14483d0fb
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_fr.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_fr",function(e){e.Intl.add("datatype-date-format","fr",{a:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],A:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],b:["janv.","f\u00e9vr.","mars","avr.","mai","juin","juil.","ao\u00fbt","sept.","oct.","nov.","d\u00e9c."],B:["janvier","f\u00e9vrier","mars","avril","mai","juin","juillet","ao\u00fbt","septembre","octobre","novembre","d\u00e9cembre"],c:"%a %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_hi-IN.js b/js/yui3/datatype-date-format/lang/datatype-date-format_hi-IN.js
new file mode 100644
index 000000000..6b2033695
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_hi-IN.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_hi-IN",function(e){e.Intl.add("datatype-date-format","hi-IN",{a:["\u0930\u0935\u093f","\u0938\u094b\u092e","\u092e\u0902\u0917\u0932","\u092c\u0941\u0927","\u0917\u0941\u0930\u0941","\u0936\u0941\u0915\u094d\u0930","\u0936\u0928\u093f"],A:["\u0930\u0935\u093f\u0935\u093e\u0930","\u0938\u094b\u092e\u0935\u093e\u0930","\u092e\u0902\u0917\u0932\u0935\u093e\u0930","\u092c\u0941\u0927\u0935\u093e\u0930","\u0917\u0941\u0930\u0941\u0935\u093e\u0930","\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930","\u0936\u0928\u093f\u0935\u093e\u0930"],b:["\u091c\u0928\u0935\u0930\u0940","\u092b\u0930\u0935\u0930\u0940","\u092e\u093e\u0930\u094d\u091a","\u0905\u092a\u094d\u0930\u0948\u0932","\u092e\u0908","\u091c\u0942\u0928","\u091c\u0941\u0932\u093e\u0908","\u0905\u0917\u0938\u094d\u0924","\u0938\u093f\u0924\u092e\u094d\u092c\u0930","\u0905\u0915\u094d\u0924\u0942\u092c\u0930","\u0928\u0935\u092e\u094d\u092c\u0930","\u0926\u093f\u0938\u092e\u094d\u092c\u0930"],B:["\u091c\u0928\u0935\u0930\u0940","\u092b\u0930\u0935\u0930\u0940","\u092e\u093e\u0930\u094d\u091a","\u0905\u092a\u094d\u0930\u0948\u0932","\u092e\u0908","\u091c\u0942\u0928","\u091c\u0941\u0932\u093e\u0908","\u0905\u0917\u0938\u094d\u0924","\u0938\u093f\u0924\u092e\u094d\u092c\u0930","\u0905\u0915\u094d\u0924\u0942\u092c\u0930","\u0928\u0935\u092e\u094d\u092c\u0930","\u0926\u093f\u0938\u092e\u094d\u092c\u0930"],c:"%a, %d %b %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_hi.js b/js/yui3/datatype-date-format/lang/datatype-date-format_hi.js
new file mode 100644
index 000000000..dcdb4b998
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_hi.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_hi",function(e){e.Intl.add("datatype-date-format","hi",{a:["\u0930\u0935\u093f","\u0938\u094b\u092e","\u092e\u0902\u0917\u0932","\u092c\u0941\u0927","\u0917\u0941\u0930\u0941","\u0936\u0941\u0915\u094d\u0930","\u0936\u0928\u093f"],A:["\u0930\u0935\u093f\u0935\u093e\u0930","\u0938\u094b\u092e\u0935\u093e\u0930","\u092e\u0902\u0917\u0932\u0935\u093e\u0930","\u092c\u0941\u0927\u0935\u093e\u0930","\u0917\u0941\u0930\u0941\u0935\u093e\u0930","\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930","\u0936\u0928\u093f\u0935\u093e\u0930"],b:["\u091c\u0928\u0935\u0930\u0940","\u092b\u0930\u0935\u0930\u0940","\u092e\u093e\u0930\u094d\u091a","\u0905\u092a\u094d\u0930\u0948\u0932","\u092e\u0908","\u091c\u0942\u0928","\u091c\u0941\u0932\u093e\u0908","\u0905\u0917\u0938\u094d\u0924","\u0938\u093f\u0924\u092e\u094d\u092c\u0930","\u0905\u0915\u094d\u0924\u0942\u092c\u0930","\u0928\u0935\u092e\u094d\u092c\u0930","\u0926\u093f\u0938\u092e\u094d\u092c\u0930"],B:["\u091c\u0928\u0935\u0930\u0940","\u092b\u0930\u0935\u0930\u0940","\u092e\u093e\u0930\u094d\u091a","\u0905\u092a\u094d\u0930\u0948\u0932","\u092e\u0908","\u091c\u0942\u0928","\u091c\u0941\u0932\u093e\u0908","\u0905\u0917\u0938\u094d\u0924","\u0938\u093f\u0924\u092e\u094d\u092c\u0930","\u0905\u0915\u094d\u0924\u0942\u092c\u0930","\u0928\u0935\u092e\u094d\u092c\u0930","\u0926\u093f\u0938\u092e\u094d\u092c\u0930"],c:"%a, %d %b %Y %l:%M:%S %p %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%l:%M:%S %p"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_id-ID.js b/js/yui3/datatype-date-format/lang/datatype-date-format_id-ID.js
new file mode 100644
index 000000000..287127029
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_id-ID.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_id-ID",function(e){e.Intl.add("datatype-date-format","id-ID",{a:["Min","Sen","Sel","Rab","Kam","Jum","Sab"],A:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],b:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],B:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],c:"%a, %Y %b %d %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_id.js b/js/yui3/datatype-date-format/lang/datatype-date-format_id.js
new file mode 100644
index 000000000..f42bbec39
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_id.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_id",function(e){e.Intl.add("datatype-date-format","id",{a:["Min","Sen","Sel","Rab","Kam","Jum","Sab"],A:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],b:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],B:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],c:"%a, %Y %b %d %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_it-IT.js b/js/yui3/datatype-date-format/lang/datatype-date-format_it-IT.js
new file mode 100644
index 000000000..b9ff5938b
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_it-IT.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_it-IT",function(e){e.Intl.add("datatype-date-format","it-IT",{a:["dom","lun","mar","mer","gio","ven","sab"],A:["domenica","luned\u00ec","marted\u00ec","mercoled\u00ec","gioved\u00ec","venerd\u00ec","sabato"],b:["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],B:["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],c:"%a %d %b %Y %H.%M.%S %Z",p:["M.","P."],P:["m.","p."],x:"%d/%m/%y",X:"%H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_it.js b/js/yui3/datatype-date-format/lang/datatype-date-format_it.js
new file mode 100644
index 000000000..a316c858b
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_it.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_it",function(e){e.Intl.add("datatype-date-format","it",{a:["dom","lun","mar","mer","gio","ven","sab"],A:["domenica","luned\u00ec","marted\u00ec","mercoled\u00ec","gioved\u00ec","venerd\u00ec","sabato"],b:["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],B:["gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre"],c:"%a %d %b %Y %H.%M.%S %Z",p:["M.","P."],P:["m.","p."],x:"%d/%m/%y",X:"%H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ja-JP.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ja-JP.js
new file mode 100644
index 000000000..f90b77a08
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ja-JP.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ja-JP",function(e){e.Intl.add("datatype-date-format","ja-JP",{a:["\u65e5","\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f"],A:["\u65e5\u66dc\u65e5","\u6708\u66dc\u65e5","\u706b\u66dc\u65e5","\u6c34\u66dc\u65e5","\u6728\u66dc\u65e5","\u91d1\u66dc\u65e5","\u571f\u66dc\u65e5"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%m\u6708%d\u65e5(%a)%k\u6642%M\u5206%S\u79d2 %Z",p:["\u5348\u524d","\u5348\u5f8c"],P:["\u5348\u524d","\u5348\u5f8c"],x:"%y/%m/%d",X:"%k\u6642%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ja.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ja.js
new file mode 100644
index 000000000..ada43e4c4
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ja.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ja",function(e){e.Intl.add("datatype-date-format","ja",{a:["\u65e5","\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f"],A:["\u65e5\u66dc\u65e5","\u6708\u66dc\u65e5","\u706b\u66dc\u65e5","\u6c34\u66dc\u65e5","\u6728\u66dc\u65e5","\u91d1\u66dc\u65e5","\u571f\u66dc\u65e5"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%m\u6708%d\u65e5(%a)%k\u6642%M\u5206%S\u79d2 %Z",p:["\u5348\u524d","\u5348\u5f8c"],P:["\u5348\u524d","\u5348\u5f8c"],x:"%y/%m/%d",X:"%k\u6642%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ko-KR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ko-KR.js
new file mode 100644
index 000000000..fa96a5fcd
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ko-KR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ko-KR",function(e){e.Intl.add("datatype-date-format","ko-KR",{a:["\uc77c","\uc6d4","\ud654","\uc218","\ubaa9","\uae08","\ud1a0"],A:["\uc77c\uc694\uc77c","\uc6d4\uc694\uc77c","\ud654\uc694\uc77c","\uc218\uc694\uc77c","\ubaa9\uc694\uc77c","\uae08\uc694\uc77c","\ud1a0\uc694\uc77c"],b:["1\uc6d4","2\uc6d4","3\uc6d4","4\uc6d4","5\uc6d4","6\uc6d4","7\uc6d4","8\uc6d4","9\uc6d4","10\uc6d4","11\uc6d4","12\uc6d4"],B:["1\uc6d4","2\uc6d4","3\uc6d4","4\uc6d4","5\uc6d4","6\uc6d4","7\uc6d4","8\uc6d4","9\uc6d4","10\uc6d4","11\uc6d4","12\uc6d4"],c:"%Y\ub144 %b %d\uc77c %a%p %I\uc2dc %M\ubd84 %S\ucd08 %Z",p:["\uc624\uc804","\uc624\ud6c4"],P:["\uc624\uc804","\uc624\ud6c4"],x:"%y. %m. %d.",X:"%p %I\uc2dc %M\ubd84 %S\ucd08"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ko.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ko.js
new file mode 100644
index 000000000..f6022a672
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ko.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ko",function(e){e.Intl.add("datatype-date-format","ko",{a:["\uc77c","\uc6d4","\ud654","\uc218","\ubaa9","\uae08","\ud1a0"],A:["\uc77c\uc694\uc77c","\uc6d4\uc694\uc77c","\ud654\uc694\uc77c","\uc218\uc694\uc77c","\ubaa9\uc694\uc77c","\uae08\uc694\uc77c","\ud1a0\uc694\uc77c"],b:["1\uc6d4","2\uc6d4","3\uc6d4","4\uc6d4","5\uc6d4","6\uc6d4","7\uc6d4","8\uc6d4","9\uc6d4","10\uc6d4","11\uc6d4","12\uc6d4"],B:["1\uc6d4","2\uc6d4","3\uc6d4","4\uc6d4","5\uc6d4","6\uc6d4","7\uc6d4","8\uc6d4","9\uc6d4","10\uc6d4","11\uc6d4","12\uc6d4"],c:"%Y\ub144 %b %d\uc77c %a%p %I\uc2dc %M\ubd84 %S\ucd08 %Z",p:["\uc624\uc804","\uc624\ud6c4"],P:["\uc624\uc804","\uc624\ud6c4"],x:"%y. %m. %d.",X:"%p %I\uc2dc %M\ubd84 %S\ucd08"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ms-MY.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ms-MY.js
new file mode 100644
index 000000000..57b8e7d75
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ms-MY.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ms-MY",function(e){e.Intl.add("datatype-date-format","ms-MY",{a:["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],A:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],b:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],B:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],c:"%a, %Y %b %d %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%Y-%m-%d",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ms.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ms.js
new file mode 100644
index 000000000..2d16756c3
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ms.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ms",function(e){e.Intl.add("datatype-date-format","ms",{a:["Ahd","Isn","Sel","Rab","Kha","Jum","Sab"],A:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],b:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis"],B:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],c:"%a, %Y %b %d %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%Y-%m-%d",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_nb-NO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_nb-NO.js
new file mode 100644
index 000000000..7f1790943
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_nb-NO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_nb-NO",function(e){e.Intl.add("datatype-date-format","nb-NO",{a:["s\u00f8n.","man.","tir.","ons.","tor.","fre.","l\u00f8r."],A:["s\u00f8ndag","mandag","tirsdag","onsdag","torsdag","fredag","l\u00f8rdag"],b:["jan.","feb.","mars","apr.","mai","juni","juli","aug.","sep.","okt.","nov.","des."],B:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],c:"%a %d. %b %Y kl. %H.%M.%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%y",X:"kl. %H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_nb.js b/js/yui3/datatype-date-format/lang/datatype-date-format_nb.js
new file mode 100644
index 000000000..a810d17cb
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_nb.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_nb",function(e){e.Intl.add("datatype-date-format","nb",{a:["s\u00f8n.","man.","tir.","ons.","tor.","fre.","l\u00f8r."],A:["s\u00f8ndag","mandag","tirsdag","onsdag","torsdag","fredag","l\u00f8rdag"],b:["jan.","feb.","mars","apr.","mai","juni","juli","aug.","sep.","okt.","nov.","des."],B:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],c:"%a %d. %b %Y kl. %H.%M.%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%y",X:"kl. %H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_nl-BE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_nl-BE.js
new file mode 100644
index 000000000..2a034f002
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_nl-BE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_nl-BE",function(e){e.Intl.add("datatype-date-format","nl-BE",{a:["zo","ma","di","wo","do","vr","za"],A:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],b:["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],B:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],c:"%a %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_nl-NL.js b/js/yui3/datatype-date-format/lang/datatype-date-format_nl-NL.js
new file mode 100644
index 000000000..946f51413
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_nl-NL.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_nl-NL",function(e){e.Intl.add("datatype-date-format","nl-NL",{a:["zo","ma","di","wo","do","vr","za"],A:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],b:["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],B:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],c:"%a %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_nl.js b/js/yui3/datatype-date-format/lang/datatype-date-format_nl.js
new file mode 100644
index 000000000..d0b85d7a2
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_nl.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_nl",function(e){e.Intl.add("datatype-date-format","nl",{a:["zo","ma","di","wo","do","vr","za"],A:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],b:["jan.","feb.","mrt.","apr.","mei","jun.","jul.","aug.","sep.","okt.","nov.","dec."],B:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],c:"%a %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_pl-PL.js b/js/yui3/datatype-date-format/lang/datatype-date-format_pl-PL.js
new file mode 100644
index 000000000..52585499e
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_pl-PL.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_pl-PL",function(e){e.Intl.add("datatype-date-format","pl-PL",{a:["niedz.","pon.","wt.","\u015br.","czw.","pt.","sob."],A:["niedziela","poniedzia\u0142ek","wtorek","\u015broda","czwartek","pi\u0105tek","sobota"],b:["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","pa\u017a","lis","gru"],B:["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","wrze\u015bnia","pa\u017adziernika","listopada","grudnia"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_pl.js b/js/yui3/datatype-date-format/lang/datatype-date-format_pl.js
new file mode 100644
index 000000000..d4dffcb51
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_pl.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_pl",function(e){e.Intl.add("datatype-date-format","pl",{a:["niedz.","pon.","wt.","\u015br.","czw.","pt.","sob."],A:["niedziela","poniedzia\u0142ek","wtorek","\u015broda","czwartek","pi\u0105tek","sobota"],b:["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","pa\u017a","lis","gru"],B:["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","wrze\u015bnia","pa\u017adziernika","listopada","grudnia"],c:"%a, %d %b %Y %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d-%m-%y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_pt-BR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_pt-BR.js
new file mode 100644
index 000000000..4c688ce36
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_pt-BR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_pt-BR",function(e){e.Intl.add("datatype-date-format","pt-BR",{a:["dom","seg","ter","qua","qui","sex","s\u00e1b"],A:["domingo","segunda-feira","ter\u00e7a-feira","quarta-feira","quinta-feira","sexta-feira","s\u00e1bado"],b:["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],B:["janeiro","fevereiro","mar\u00e7o","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],c:"%a, %d de %b de %Y %Hh%Mmin%Ss %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%Hh%Mmin%Ss"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_pt.js b/js/yui3/datatype-date-format/lang/datatype-date-format_pt.js
new file mode 100644
index 000000000..0469e1753
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_pt.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_pt",function(e){e.Intl.add("datatype-date-format","pt",{a:["dom","seg","ter","qua","qui","sex","s\u00e1b"],A:["domingo","segunda-feira","ter\u00e7a-feira","quarta-feira","quinta-feira","sexta-feira","s\u00e1bado"],b:["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],B:["janeiro","fevereiro","mar\u00e7o","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],c:"%a, %d de %b de %Y %Hh%Mmin%Ss %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%Hh%Mmin%Ss"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ro-RO.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ro-RO.js
new file mode 100644
index 000000000..51ae32647
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ro-RO.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ro-RO",function(e){e.Intl.add("datatype-date-format","ro-RO",{a:["Du","Lu","Ma","Mi","Jo","Vi","S\u00e2"],A:["duminic\u0103","luni","mar\u021bi","miercuri","joi","vineri","s\u00e2mb\u0103t\u0103"],b:["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],B:["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],c:"%a, %d %b %Y, %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ro.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ro.js
new file mode 100644
index 000000000..adbc1f263
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ro.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ro",function(e){e.Intl.add("datatype-date-format","ro",{a:["Du","Lu","Ma","Mi","Jo","Vi","S\u00e2"],A:["duminic\u0103","luni","mar\u021bi","miercuri","joi","vineri","s\u00e2mb\u0103t\u0103"],b:["ian.","feb.","mar.","apr.","mai","iun.","iul.","aug.","sept.","oct.","nov.","dec."],B:["ianuarie","februarie","martie","aprilie","mai","iunie","iulie","august","septembrie","octombrie","noiembrie","decembrie"],c:"%a, %d %b %Y, %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ru-RU.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ru-RU.js
new file mode 100644
index 000000000..4aba7a4b0
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ru-RU.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ru-RU",function(e){e.Intl.add("datatype-date-format","ru-RU",{a:["\u0412\u0441","\u041f\u043d","\u0412\u0442","\u0421\u0440","\u0427\u0442","\u041f\u0442","\u0421\u0431"],A:["\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435","\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a","\u0432\u0442\u043e\u0440\u043d\u0438\u043a","\u0441\u0440\u0435\u0434\u0430","\u0447\u0435\u0442\u0432\u0435\u0440\u0433","\u043f\u044f\u0442\u043d\u0438\u0446\u0430","\u0441\u0443\u0431\u0431\u043e\u0442\u0430"],b:["\u044f\u043d\u0432.","\u0444\u0435\u0432\u0440.","\u043c\u0430\u0440\u0442\u0430","\u0430\u043f\u0440.","\u043c\u0430\u044f","\u0438\u044e\u043d\u044f","\u0438\u044e\u043b\u044f","\u0430\u0432\u0433.","\u0441\u0435\u043d\u0442.","\u043e\u043a\u0442.","\u043d\u043e\u044f\u0431.","\u0434\u0435\u043a."],B:["\u044f\u043d\u0432\u0430\u0440\u044f","\u0444\u0435\u0432\u0440\u0430\u043b\u044f","\u043c\u0430\u0440\u0442\u0430","\u0430\u043f\u0440\u0435\u043b\u044f","\u043c\u0430\u044f","\u0438\u044e\u043d\u044f","\u0438\u044e\u043b\u044f","\u0430\u0432\u0433\u0443\u0441\u0442\u0430","\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f","\u043e\u043a\u0442\u044f\u0431\u0440\u044f","\u043d\u043e\u044f\u0431\u0440\u044f","\u0434\u0435\u043a\u0430\u0431\u0440\u044f"],c:"%a, %d %b %Y %k:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%y",X:"%k:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_ru.js b/js/yui3/datatype-date-format/lang/datatype-date-format_ru.js
new file mode 100644
index 000000000..d6f3eb3a2
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_ru.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_ru",function(e){e.Intl.add("datatype-date-format","ru",{a:["\u0412\u0441","\u041f\u043d","\u0412\u0442","\u0421\u0440","\u0427\u0442","\u041f\u0442","\u0421\u0431"],A:["\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435","\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a","\u0432\u0442\u043e\u0440\u043d\u0438\u043a","\u0441\u0440\u0435\u0434\u0430","\u0447\u0435\u0442\u0432\u0435\u0440\u0433","\u043f\u044f\u0442\u043d\u0438\u0446\u0430","\u0441\u0443\u0431\u0431\u043e\u0442\u0430"],b:["\u044f\u043d\u0432.","\u0444\u0435\u0432\u0440.","\u043c\u0430\u0440\u0442\u0430","\u0430\u043f\u0440.","\u043c\u0430\u044f","\u0438\u044e\u043d\u044f","\u0438\u044e\u043b\u044f","\u0430\u0432\u0433.","\u0441\u0435\u043d\u0442.","\u043e\u043a\u0442.","\u043d\u043e\u044f\u0431.","\u0434\u0435\u043a."],B:["\u044f\u043d\u0432\u0430\u0440\u044f","\u0444\u0435\u0432\u0440\u0430\u043b\u044f","\u043c\u0430\u0440\u0442\u0430","\u0430\u043f\u0440\u0435\u043b\u044f","\u043c\u0430\u044f","\u0438\u044e\u043d\u044f","\u0438\u044e\u043b\u044f","\u0430\u0432\u0433\u0443\u0441\u0442\u0430","\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f","\u043e\u043a\u0442\u044f\u0431\u0440\u044f","\u043d\u043e\u044f\u0431\u0440\u044f","\u0434\u0435\u043a\u0430\u0431\u0440\u044f"],c:"%a, %d %b %Y %k:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%y",X:"%k:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_sv-SE.js b/js/yui3/datatype-date-format/lang/datatype-date-format_sv-SE.js
new file mode 100644
index 000000000..0cc35f8b9
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_sv-SE.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_sv-SE",function(e){e.Intl.add("datatype-date-format","sv-SE",{a:["s\u00f6n","m\u00e5n","tis","ons","tors","fre","l\u00f6r"],A:["s\u00f6ndag","m\u00e5ndag","tisdag","onsdag","torsdag","fredag","l\u00f6rdag"],b:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],B:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],c:"%a %d %b %Y kl. %H.%M.%S %Z",p:["FM","EM"],P:["fm","em"],x:"%Y-%m-%d",X:"kl. %H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_sv.js b/js/yui3/datatype-date-format/lang/datatype-date-format_sv.js
new file mode 100644
index 000000000..d26339dd3
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_sv.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_sv",function(e){e.Intl.add("datatype-date-format","sv",{a:["s\u00f6n","m\u00e5n","tis","ons","tors","fre","l\u00f6r"],A:["s\u00f6ndag","m\u00e5ndag","tisdag","onsdag","torsdag","fredag","l\u00f6rdag"],b:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],B:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],c:"%a %d %b %Y kl. %H.%M.%S %Z",p:["FM","EM"],P:["fm","em"],x:"%Y-%m-%d",X:"kl. %H.%M.%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_th-TH.js b/js/yui3/datatype-date-format/lang/datatype-date-format_th-TH.js
new file mode 100644
index 000000000..54e6b6024
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_th-TH.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_th-TH",function(e){e.Intl.add("datatype-date-format","th-TH",{a:["\u0e2d\u0e32.","\u0e08.","\u0e2d.","\u0e1e.","\u0e1e\u0e24.","\u0e28.","\u0e2a."],A:["\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c","\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c","\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23","\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18","\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35","\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c","\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"],b:["\u0e21.\u0e04.","\u0e01.\u0e1e.","\u0e21\u0e35.\u0e04.","\u0e40\u0e21.\u0e22.","\u0e1e.\u0e04.","\u0e21\u0e34.\u0e22.","\u0e01.\u0e04.","\u0e2a.\u0e04.","\u0e01.\u0e22.","\u0e15.\u0e04.","\u0e1e.\u0e22.","\u0e18.\u0e04."],B:["\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21","\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c","\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21","\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19","\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21","\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19","\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21","\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21","\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19","\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21","\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19","\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"],c:"%a %d %b %Y, %k \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 %M \u0e19\u0e32\u0e17\u0e35 %S \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35 %Z",p:["\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07","\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"],P:["\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07","\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"],x:"%d/%m/%Y",X:"%k \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 %M \u0e19\u0e32\u0e17\u0e35 %S \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_th.js b/js/yui3/datatype-date-format/lang/datatype-date-format_th.js
new file mode 100644
index 000000000..bf82e92fd
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_th.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_th",function(e){e.Intl.add("datatype-date-format","th",{a:["\u0e2d\u0e32.","\u0e08.","\u0e2d.","\u0e1e.","\u0e1e\u0e24.","\u0e28.","\u0e2a."],A:["\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c","\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c","\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23","\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18","\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35","\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c","\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"],b:["\u0e21.\u0e04.","\u0e01.\u0e1e.","\u0e21\u0e35.\u0e04.","\u0e40\u0e21.\u0e22.","\u0e1e.\u0e04.","\u0e21\u0e34.\u0e22.","\u0e01.\u0e04.","\u0e2a.\u0e04.","\u0e01.\u0e22.","\u0e15.\u0e04.","\u0e1e.\u0e22.","\u0e18.\u0e04."],B:["\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21","\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c","\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21","\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19","\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21","\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19","\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21","\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21","\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19","\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21","\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19","\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"],c:"%a %d %b %Y, %k \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 %M \u0e19\u0e32\u0e17\u0e35 %S \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35 %Z",p:["\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07","\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"],P:["\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07","\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"],x:"%d/%m/%Y",X:"%k \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 %M \u0e19\u0e32\u0e17\u0e35 %S \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_tr-TR.js b/js/yui3/datatype-date-format/lang/datatype-date-format_tr-TR.js
new file mode 100644
index 000000000..75eafaac1
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_tr-TR.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_tr-TR",function(e){e.Intl.add("datatype-date-format","tr-TR",{a:["Paz","Pzt","Sal","\u00c7ar","Per","Cum","Cmt"],A:["Pazar","Pazartesi","Sal\u0131","\u00c7ar\u015famba","Per\u015fembe","Cuma","Cumartesi"],b:["Oca","\u015eub","Mar","Nis","May","Haz","Tem","A\u011fu","Eyl","Eki","Kas","Ara"],B:["Ocak","\u015eubat","Mart","Nisan","May\u0131s","Haziran","Temmuz","A\u011fustos","Eyl\u00fcl","Ekim","Kas\u0131m","Aral\u0131k"],c:"%d %b %Y %a %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_tr.js b/js/yui3/datatype-date-format/lang/datatype-date-format_tr.js
new file mode 100644
index 000000000..7557eaf58
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_tr.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_tr",function(e){e.Intl.add("datatype-date-format","tr",{a:["Paz","Pzt","Sal","\u00c7ar","Per","Cum","Cmt"],A:["Pazar","Pazartesi","Sal\u0131","\u00c7ar\u015famba","Per\u015fembe","Cuma","Cumartesi"],b:["Oca","\u015eub","Mar","Nis","May","Haz","Tem","A\u011fu","Eyl","Eki","Kas","Ara"],B:["Ocak","\u015eubat","Mart","Nisan","May\u0131s","Haziran","Temmuz","A\u011fustos","Eyl\u00fcl","Ekim","Kas\u0131m","Aral\u0131k"],c:"%d %b %Y %a %H:%M:%S %Z",p:["AM","PM"],P:["am","pm"],x:"%d.%m.%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_vi-VN.js b/js/yui3/datatype-date-format/lang/datatype-date-format_vi-VN.js
new file mode 100644
index 000000000..98cc0ccdc
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_vi-VN.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_vi-VN",function(e){e.Intl.add("datatype-date-format","vi-VN",{a:["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],A:["Ch\u1ee7 nh\u1eadt","Th\u1ee9 hai","Th\u1ee9 ba","Th\u1ee9 t\u01b0","Th\u1ee9 n\u0103m","Th\u1ee9 s\u00e1u","Th\u1ee9 b\u1ea3y"],b:["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],B:["th\u00e1ng m\u1ed9t","th\u00e1ng hai","th\u00e1ng ba","th\u00e1ng t\u01b0","th\u00e1ng n\u0103m","th\u00e1ng s\u00e1u","th\u00e1ng b\u1ea3y","th\u00e1ng t\u00e1m","th\u00e1ng ch\u00edn","th\u00e1ng m\u01b0\u1eddi","th\u00e1ng m\u01b0\u1eddi m\u1ed9t","th\u00e1ng m\u01b0\u1eddi hai"],c:"%H:%M:%S %Z %a, %d %b %Y",p:["SA","CH"],P:["sa","ch"],x:"%d/%m/%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_vi.js b/js/yui3/datatype-date-format/lang/datatype-date-format_vi.js
new file mode 100644
index 000000000..ca6a679da
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_vi.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_vi",function(e){e.Intl.add("datatype-date-format","vi",{a:["CN","Th 2","Th 3","Th 4","Th 5","Th 6","Th 7"],A:["Ch\u1ee7 nh\u1eadt","Th\u1ee9 hai","Th\u1ee9 ba","Th\u1ee9 t\u01b0","Th\u1ee9 n\u0103m","Th\u1ee9 s\u00e1u","Th\u1ee9 b\u1ea3y"],b:["thg 1","thg 2","thg 3","thg 4","thg 5","thg 6","thg 7","thg 8","thg 9","thg 10","thg 11","thg 12"],B:["th\u00e1ng m\u1ed9t","th\u00e1ng hai","th\u00e1ng ba","th\u00e1ng t\u01b0","th\u00e1ng n\u0103m","th\u00e1ng s\u00e1u","th\u00e1ng b\u1ea3y","th\u00e1ng t\u00e1m","th\u00e1ng ch\u00edn","th\u00e1ng m\u01b0\u1eddi","th\u00e1ng m\u01b0\u1eddi m\u1ed9t","th\u00e1ng m\u01b0\u1eddi hai"],c:"%H:%M:%S %Z %a, %d %b %Y",p:["SA","CH"],P:["sa","ch"],x:"%d/%m/%Y",X:"%H:%M:%S"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans-CN.js b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans-CN.js
new file mode 100644
index 000000000..52e592e2e
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans-CN.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_zh-Hans-CN",function(e){e.Intl.add("datatype-date-format","zh-Hans-CN",{a:["\u5468\u65e5","\u5468\u4e00","\u5468\u4e8c","\u5468\u4e09","\u5468\u56db","\u5468\u4e94","\u5468\u516d"],A:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%b%d\u65e5%a%Z%p%l\u65f6%M\u5206%S\u79d2",p:["\u4e0a\u5348","\u4e0b\u5348"],P:["\u4e0a\u5348","\u4e0b\u5348"],x:"%y-%m-%d",X:"%p%l\u65f6%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans.js b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans.js
new file mode 100644
index 000000000..b4bbe0edd
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hans.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_zh-Hans",function(e){e.Intl.add("datatype-date-format","zh-Hans",{a:["\u5468\u65e5","\u5468\u4e00","\u5468\u4e8c","\u5468\u4e09","\u5468\u56db","\u5468\u4e94","\u5468\u516d"],A:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%b%d\u65e5%a%Z%p%l\u65f6%M\u5206%S\u79d2",p:["\u4e0a\u5348","\u4e0b\u5348"],P:["\u4e0a\u5348","\u4e0b\u5348"],x:"%y-%m-%d",X:"%p%l\u65f6%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-HK.js b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-HK.js
new file mode 100644
index 000000000..64b9e4669
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-HK.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_zh-Hant-HK",function(e){e.Intl.add("datatype-date-format","zh-Hant-HK",{a:["\u9031\u65e5","\u9031\u4e00","\u9031\u4e8c","\u9031\u4e09","\u9031\u56db","\u9031\u4e94","\u9031\u516d"],A:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%b%d\u65e5%a%Z%p%l\u6642%M\u5206%S\u79d2",p:["\u4e0a\u5348","\u4e0b\u5348"],P:["\u4e0a\u5348","\u4e0b\u5348"],x:"%y\u5e74%m\u6708%d\u65e5",X:"%p%l\u6642%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-TW.js b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-TW.js
new file mode 100644
index 000000000..0af91e454
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant-TW.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_zh-Hant-TW",function(e){e.Intl.add("datatype-date-format","zh-Hant-TW",{a:["\u9031\u65e5","\u9031\u4e00","\u9031\u4e8c","\u9031\u4e09","\u9031\u56db","\u9031\u4e94","\u9031\u516d"],A:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%b%d\u65e5%a%Z%p%l\u6642%M\u5206%S\u79d2",p:["\u4e0a\u5348","\u4e0b\u5348"],P:["\u4e0a\u5348","\u4e0b\u5348"],x:"%y/%m/%d",X:"%p%l\u6642%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant.js b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant.js
new file mode 100644
index 000000000..b6009ebbf
--- /dev/null
+++ b/js/yui3/datatype-date-format/lang/datatype-date-format_zh-Hant.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/datatype-date-format_zh-Hant",function(e){e.Intl.add("datatype-date-format","zh-Hant",{a:["\u9031\u65e5","\u9031\u4e00","\u9031\u4e8c","\u9031\u4e09","\u9031\u56db","\u9031\u4e94","\u9031\u516d"],A:["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],b:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],B:["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],c:"%Y\u5e74%b%d\u65e5%a%Z%p%l\u6642%M\u5206%S\u79d2",p:["\u4e0a\u5348","\u4e0b\u5348"],P:["\u4e0a\u5348","\u4e0b\u5348"],x:"%y/%m/%d",X:"%p%l\u6642%M\u5206%S\u79d2"})},"3.7.3");
diff --git a/js/yui3/datatype-date-math/datatype-date-math-min.js b/js/yui3/datatype-date-math/datatype-date-math-min.js
new file mode 100644
index 000000000..2ff3c7078
--- /dev/null
+++ b/js/yui3/datatype-date-math/datatype-date-math-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-date-math",function(e,t){var n=e.Lang;e.mix(e.namespace("Date"),{isValidDate:function(e){return n.isDate(e)&&isFinite(e)&&e!="Invalid Date"&&!isNaN(e)&&e!=null?!0:!1},areEqual:function(e,t){return this.isValidDate(e)&&this.isValidDate(t)&&e.getTime()==t.getTime()},isGreater:function(e,t){return this.isValidDate(e)&&this.isValidDate(t)&&e.getTime()>t.getTime()},isGreaterOrEqual:function(e,t){return this.isValidDate(e)&&this.isValidDate(t)&&e.getTime()>=t.getTime()},isInRange:function(e,t,n){return this.isGreaterOrEqual(e,t)&&this.isGreaterOrEqual(n,e)},addDays:function(e,t){return new Date(e.getTime()+864e5*t)},addMonths:function(e,t){var n=e.getFullYear(),r=e.getMonth()+t;n=Math.floor(n+r/12),r=(r%12+12)%12;var i=new Date(e.getTime());return i.setFullYear(n),i.setMonth(r),i},addYears:function(e,t){var n=e.getFullYear()+t,r=new Date(e.getTime());return r.setFullYear(n),r},listOfDatesInMonth:function(e){if(!this.isValidDate(e))return[];var t=this.daysInMonth(e),n=e.getFullYear(),r=e.getMonth(),i=[];for(var s=1;s<=t;s++)i.push(new Date(n,r,s,12,0,0));return i},daysInMonth:function(e){if(!this.isValidDate(e))return 0;var t=e.getMonth(),n=[31,28,31,30,31,30,31,31,30,31,30,31];if(t!=1)return n[t];var r=e.getFullYear();return r%400===0?29:r%100===0?28:r%4===0?29:28}}),e.namespace("DataType"),e.DataType.Date=e.Date},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/datatype-date-parse/datatype-date-parse-min.js b/js/yui3/datatype-date-parse/datatype-date-parse-min.js
new file mode 100644
index 000000000..65f22b6a3
--- /dev/null
+++ b/js/yui3/datatype-date-parse/datatype-date-parse-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-date-parse",function(e,t){var n=e.Lang;e.mix(e.namespace("Date"),{parse:function(e){var t=null;return n.isDate(e)?t:(t=new Date(e),n.isDate(t)&&t!="Invalid Date"&&!isNaN(t)?t:null)}}),e.namespace("Parsers").date=e.Date.parse,e.namespace("DataType"),e.DataType.Date=e.Date},"3.7.3");
diff --git a/js/yui3/datatype-number-format/datatype-number-format-min.js b/js/yui3/datatype-number-format/datatype-number-format-min.js
new file mode 100644
index 000000000..d97aa0366
--- /dev/null
+++ b/js/yui3/datatype-number-format/datatype-number-format-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-number-format",function(e,t){var n=e.Lang;e.mix(e.namespace("Number"),{format:function(e,t){if(n.isNumber(e)){t=t||{};var r=e<0,i=e+"",s=t.decimalPlaces,o=t.decimalSeparator||".",u=t.thousandsSeparator,a,f,l,c;n.isNumber(s)&&s>=0&&s<=20&&(i=e.toFixed(s)),o!=="."&&(i=i.replace(".",o));if(u){a=i.lastIndexOf(o),a=a>-1?a:i.length,f=i.substring(a);for(l=0,c=a;c>0;c--)l%3===0&&c!==a&&(!r||c>1)&&(f=u+f),f=i.charAt(c-1)+f,l++;i=f}return i=t.prefix?t.prefix+i:i,i=t.suffix?i+t.suffix:i,i}return n.isValue(e)&&e.toString?e.toString():""}}),e.namespace("DataType"),e.DataType.Number=e.Number},"3.7.3");
diff --git a/js/yui3/datatype-number-parse/datatype-number-parse-min.js b/js/yui3/datatype-number-parse/datatype-number-parse-min.js
new file mode 100644
index 000000000..9f6e7d5ae
--- /dev/null
+++ b/js/yui3/datatype-number-parse/datatype-number-parse-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-number-parse",function(e,t){var n=e.Lang;e.mix(e.namespace("Number"),{parse:function(e){var t=e===null?e:+e;return n.isNumber(t)?t:null}}),e.namespace("Parsers").number=e.Number.parse,e.namespace("DataType"),e.DataType.Number=e.Number},"3.7.3");
diff --git a/js/yui3/datatype-xml-format/datatype-xml-format-min.js b/js/yui3/datatype-xml-format/datatype-xml-format-min.js
new file mode 100644
index 000000000..2e84363c0
--- /dev/null
+++ b/js/yui3/datatype-xml-format/datatype-xml-format-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-xml-format",function(e,t){var n=e.Lang;e.mix(e.namespace("XML"),{format:function(e){try{if(!n.isUndefined(e.getXml))return e.getXml();if(!n.isUndefined(XMLSerializer))return(new XMLSerializer).serializeToString(e)}catch(t){return e&&e.xml?e.xml:n.isValue(e)&&e.toString?e.toString():""}}}),e.namespace("DataType"),e.DataType.XML=e.XML},"3.7.3");
diff --git a/js/yui3/datatype-xml-parse/datatype-xml-parse-min.js b/js/yui3/datatype-xml-parse/datatype-xml-parse-min.js
new file mode 100644
index 000000000..f2e2170e3
--- /dev/null
+++ b/js/yui3/datatype-xml-parse/datatype-xml-parse-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("datatype-xml-parse",function(e,t){var n=e.Lang;e.mix(e.namespace("XML"),{parse:function(e){var t=null;if(n.isString(e))try{n.isUndefined(ActiveXObject)||(t=new ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.loadXML(e))}catch(r){try{n.isUndefined(DOMParser)||(t=(new DOMParser).parseFromString(e,"text/xml")),n.isUndefined(Windows.Data.Xml.Dom)||(t=new Windows.Data.Xml.Dom.XmlDocument,t.loadXml(e))}catch(i){}}return n.isNull(t)||n.isNull(t.documentElement)||t.documentElement.nodeName==="parsererror",t}}),e.namespace("Parsers").xml=e.XML.parse,e.namespace("DataType"),e.DataType.XML=e.XML},"3.7.3");
diff --git a/js/yui3/dd-constrain/dd-constrain-min.js b/js/yui3/dd-constrain/dd-constrain-min.js
new file mode 100644
index 000000000..f316c8280
--- /dev/null
+++ b/js/yui3/dd-constrain/dd-constrain-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-constrain",function(e,t){var n="dragNode",r="offsetHeight",i="offsetWidth",s="host",o="tickXArray",u="tickYArray",a=e.DD.DDM,f="top",l="right",c="bottom",h="left",p="view",d=null,v="drag:tickAlignX",m="drag:tickAlignY",g=function(){this._lazyAddAttrs=!1,g.superclass.constructor.apply(this,arguments)};g.NAME="ddConstrained",g.NS="con",g.ATTRS={host:{},stickX:{value:!1},stickY:{value:!1},tickX:{value:!1},tickY:{value:!1},tickXArray:{value:!1},tickYArray:{value:!1},gutter:{value:"0",setter:function(t){return e.DD.DDM.cssSizestoObject(t)}},constrain:{value:p,setter:function(t){var n=e.one(t);return n&&(t=n),t}},constrain2region:{setter:function(e){return this.set("constrain",e)}},constrain2node:{setter:function(t){return this.set("constrain",e.one(t))}},constrain2view:{setter:function(){return this.set("constrain",p)}},cacheRegion:{value:!0}},d={_lastTickXFired:null,_lastTickYFired:null,initializer:function(){this._createEvents(),this._eventHandles=[this.get(s).on("drag:end",e.bind(this._handleEnd,this)),this.get(s).on("drag:start",e.bind(this._handleStart,this)),this.get(s).after("drag:align",e.bind(this.align,this)),this.get(s).after("drag:drag",e.bind(this.drag,this))]},destructor:function(){e.each(this._eventHandles,function(e){e.detach()}),this._eventHandles.length=0},_createEvents:function(){var t=[v,m];e.each(t,function(e){this.publish(e,{type:e,emitFacade:!0,bubbles:!0,queuable:!1,prefix:"drag"})},this)},_handleEnd:function(){this._lastTickYFired=null,this._lastTickXFired=null},_handleStart:function(){this.resetCache()},_regionCache:null,_cacheRegion:function(){this._regionCache=this.get("constrain").get("region")},resetCache:function(){this._regionCache=null},_getConstraint:function(){var t=this.get("constrain"),r=this.get("gutter"),i;t&&(t instanceof e.Node?(this._regionCache||(this._eventHandles.push(e.on("resize",e.bind(this._cacheRegion,this),e.config.win)),this._cacheRegion()),i=e.clone(this._regionCache),this.get("cacheRegion")||this.resetCache()):e.Lang.isObject(t)&&(i=e.clone(t)));if(!t||!i)t=p;return t===p&&(i=this.get(s).get(n).get("viewportRegion")),e.each(r,function(e,t){t===l||t===c?i[t]-=e:i[t]+=e}),i},getRegion:function(e){var t={},o=null,u=null,a=this.get(s);return t=this._getConstraint(),e&&(o=a.get(n).get(r),u=a.get(n).get(i),t[l]=t[l]-u,t[c]=t[c]-o),t},_checkRegion:function(e){var t=e,o=this.getRegion(),u=this.get(s),a=u.get(n).get(r),p=u.get(n).get(i);return t[1]>o[c]-a&&(e[1]=o[c]-a),o[f]>t[1]&&(e[1]=o[f]),t[0]>o[l]-p&&(e[0]=o[l]-p),o[h]>t[0]&&(e[0]=o[h]),e},inRegion:function(e){e=e||this.get(s).get(n).getXY();var t=this._checkRegion([e[0],e[1]]),r=!1;return e[0]===t[0]&&e[1]===t[1]&&(r=!0),r},align:function(){var e=this.get(s),t=[e.actXY[0],e.actXY[1]],n=this.getRegion(!0);this.get("stickX")&&(t[1]=e.startXY[1]-e.deltaXY[1]),this.get("stickY")&&(t[0]=e.startXY[0]-e.deltaXY[0]),n&&(t=this._checkRegion(t)),t=this._checkTicks(t,n),e.actXY=t},drag:function(){var t=this.get(s),n=this.get("tickX"),r=this.get("tickY"),i=[t.actXY[0],t.actXY[1]];(e.Lang.isNumber(n)||this.get(o))&&this._lastTickXFired!==i[0]&&(this._tickAlignX(),this._lastTickXFired=i[0]),(e.Lang.isNumber(r)||this.get(u))&&this._lastTickYFired!==i[1]&&(this._tickAlignY(),this._lastTickYFired=i[1])},_checkTicks:function(e,t){var n=this.get(s),r=n.startXY[0]-n.deltaXY[0],i=n.startXY[1]-n.deltaXY[1],p=this.get("tickX"),d=this.get("tickY");return p&&!this.get(o)&&(e[0]=a._calcTicks(e[0],r,p,t[h],t[l])),d&&!this.get(u)&&(e[1]=a._calcTicks(e[1],i,d,t[f],t[c])),this.get(o)&&(e[0]=a._calcTickArray(e[0],this.get(o),t[h],t[l])),this.get(u)&&(e[1]=a._calcTickArray(e[1],this.get(u),t[f],t[c])),e},_tickAlignX:function(){this.fire(v)},_tickAlignY:function(){this.fire(m)}},e.namespace("Plugin"),e.extend(g,e.Base,d),e.Plugin.DDConstrained=g,e.mix(a,{_calcTicks:function(e,t,n,r,i){var s=(e-t)/n,o=Math.floor(s),u=Math.ceil(s);return(o!==0||u!==0)&&s>=o&&s<=u&&(e=t+n*o,r&&i&&(e<r&&(e=t+n*(o+1)),e>i&&(e=t+n*(o-1)))),e},_calcTickArray:function(e,t,n,r){var i=0,s=t.length,o=0,u,a,f;if(!t||t.length===0)return e;if(t[0]>=e)return t[0];for(i=0;i<s;i++){o=i+1;if(t[o]&&t[o]>=e)return u=e-t[i],a=t[o]-e,f=a>u?t[i]:t[o],n&&r&&f>r&&(t[i]?f=t[i]:f=t[s-1]),f}return t[t.length-1]}})},"3.7.3",{requires:["dd-drag"]});
diff --git a/js/yui3/dd-ddm-base/dd-ddm-base-min.js b/js/yui3/dd-ddm-base/dd-ddm-base-min.js
new file mode 100644
index 000000000..deac6e861
--- /dev/null
+++ b/js/yui3/dd-ddm-base/dd-ddm-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-ddm-base",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};n.NAME="ddm",n.ATTRS={dragCursor:{value:"move"},clickPixelThresh:{value:3},clickTimeThresh:{value:1e3},throttleTime:{value:-1},dragMode:{value:"point",setter:function(e){return this._setDragMode(e),e}}},e.extend(n,e.Base,{_createPG:function(){},_active:null,_setDragMode:function(t){t===null&&(t=e.DD.DDM.get("dragMode"));switch(t){case 1:case"intersect":return 1;case 2:case"strict":return 2;case 0:case"point":return 0}return 0},CSS_PREFIX:e.ClassNameManager.getClassName("dd"),_activateTargets:function(){},_drags:[],activeDrag:!1,_regDrag:function(e){return this.getDrag(e.get("node"))?!1:(this._active||this._setupListeners(),this._drags.push(e),!0)},_unregDrag:function(t){var n=[];e.each(this._drags,function(e){e!==t&&(n[n.length]=e)}),this._drags=n},_setupListeners:function(){this._createPG(),this._active=!0;var t=e.one(e.config.doc);t.on("mousemove",e.throttle(e.bind(this._docMove,this),this.get("throttleTime"))),t.on("mouseup",e.bind(this._end,this))},_start:function(){this.fire("ddm:start"),this._startDrag()},_startDrag:function(){},_endDrag:function(){},_dropMove:function(){},_end:function(){this.activeDrag&&(this._shimming=!1,this._endDrag(),this.fire("ddm:end"),this.activeDrag.end.call(this.activeDrag),this.activeDrag=null)},stopDrag:function(){return this.activeDrag&&this._end(),this},_shimming:!1,_docMove:function(e){this._shimming||this._move(e)},_move:function(e){this.activeDrag&&(this.activeDrag._move.call(this.activeDrag,e),this._dropMove())},cssSizestoObject:function(e){var t=e.split(" ");switch(t.length){case 1:t[1]=t[2]=t[3]=t[0];break;case 2:t[2]=t[0],t[3]=t[1];break;case 3:t[3]=t[1]}return{top:parseInt(t[0],10),right:parseInt(t[1],10),bottom:parseInt(t[2],10),left:parseInt(t[3],10)}},getDrag:function(t){var n=!1,r=e.one(t);return r instanceof e.Node&&e.each(this._drags,function(e){r.compareTo(e.get("node"))&&(n=e)}),n},swapPosition:function(t,n){t=e.DD.DDM.getNode(t),n=e.DD.DDM.getNode(n);var r=t.getXY(),i=n.getXY();return t.setXY(i),n.setXY(r),t},getNode:function(t){return t instanceof e.Node?t:(t&&t.get?e.Widget&&t instanceof e.Widget?t=t.get("boundingBox"):t=t.get("node"):t=e.one(t),t)},swapNode:function(t,n){t=e.DD.DDM.getNode(t),n=e.DD.DDM.getNode(n);var r=n.get("parentNode"),i=n.get("nextSibling");return i===t?r.insertBefore(t,n):n===t.get("nextSibling")?r.insertBefore(n,t):(t.get("parentNode").replaceChild(n,t),r.insertBefore(t,i)),t}}),e.namespace("DD"),e.DD.DDM=new n},"3.7.3",{requires:["node","base","yui-throttle","classnamemanager"]});
diff --git a/js/yui3/dd-ddm-drop/dd-ddm-drop-min.js b/js/yui3/dd-ddm-drop/dd-ddm-drop-min.js
new file mode 100644
index 000000000..1ba41fefe
--- /dev/null
+++ b/js/yui3/dd-ddm-drop/dd-ddm-drop-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-ddm-drop",function(e,t){e.mix(e.DD.DDM,{_noShim:!1,_activeShims:[],_hasActiveShim:function(){return this._noShim?!0:this._activeShims.length},_addActiveShim:function(e){this._activeShims[this._activeShims.length]=e},_removeActiveShim:function(t){var n=[];e.each(this._activeShims,function(e){e._yuid!==t._yuid&&(n[n.length]=e)}),this._activeShims=n},syncActiveShims:function(t){e.later(0,this,function(t){var n=t?this.targets:this._lookup();e.each(n,function(e){e.sizeShim.call(e)},this)},t)},mode:0,POINT:0,INTERSECT:1,STRICT:2,useHash:!0,activeDrop:null,validDrops:[],otherDrops:{},targets:[],_addValid:function(e){return this.validDrops[this.validDrops.length]=e,this},_removeValid:function(t){var n=[];return e.each(this.validDrops,function(e){e!==t&&(n[n.length]=e)}),this.validDrops=n,this},isOverTarget:function(e){if(this.activeDrag&&e){var t=this.activeDrag.mouseXY,n,r=this.activeDrag.get("dragMode"),i,s=e.shim;if(t&&this.activeDrag){i=this.activeDrag.region;if(r===this.STRICT)return this.activeDrag.get("dragNode").inRegion(e.region,!0,i);if(e&&e.shim)return r===this.INTERSECT&&this._noShim?(n=i||this.activeDrag.get("node"),e.get("node").intersect(n,e.region).inRegion):(this._noShim&&(s=e.get("node")),s.intersect({top:t[1],bottom:t[1],left:t[0],right:t[0]},e.region).inRegion)}}return!1},clearCache:function(){this.validDrops=[],this.otherDrops={},this._activeShims=[]},_activateTargets:function(){this._noShim=!0,this.clearCache(),e.each(this.targets,function(e){e._activateShim([]),e.get("noShim")===!0&&(this._noShim=!1)},this),this._handleTargetOver()},getBestMatch:function(t,n){var r=null,i=0,s;return e.each(t,function(e){var t=this.activeDrag.get("dragNode").intersect(e.get("node"));e.region.area=t.area,t.inRegion&&t.area>i&&(i=t.area,r=e)},this),n?(s=[],e.each(t,function(e){e!==r&&(s[s.length]=e)},this),[r,s]):r},_deactivateTargets:function(){var t=[],n,r=this.activeDrag,i=this.activeDrop;r&&i&&this.otherDrops[i]?(r.get("dragMode")?(n=this.getBestMatch(this.otherDrops,!0),i=n[0],t=n[1]):(t=this.otherDrops,delete t[i]),r.get("node").removeClass(this.CSS_PREFIX+"-drag-over"),i&&(i.fire("drop:hit",{drag:r,drop:i,others:t}),r.fire("drag:drophit",{drag:r,drop:i,others:t}))):r&&r.get("dragging")&&(r.get("node").removeClass(this.CSS_PREFIX+"-drag-over"),r.fire("drag:dropmiss",{pageX:r.lastXY[0],pageY:r.lastXY[1]})),this.activeDrop=null,e.each(this.targets,function(e){e._deactivateShim([])},this)},_dropMove:function(){this._hasActiveShim()?this._handleTargetOver():e.each(this.otherDrops,function(e){e._handleOut.apply(e,[])})},_lookup:function(){if(!this.useHash||this._noShim)return this.validDrops;var t=[];return e.each(this.validDrops,function(e){e.shim&&e.shim.inViewportRegion(!1,e.region)&&(t[t.length]=e)}),t},_handleTargetOver:function(){var t=this._lookup();e.each(t,function(e){e._handleTargetOver.call(e)},this)},_regTarget:function(e){this.targets[this.targets.length]=e},_unregTarget:function(t){var n=[],r;e.each(this.targets,function(e){e!==t&&(n[n.length]=e)},this),this.targets=n,r=[],e.each(this.validDrops,function(e){e!==t&&(r[r.length]=e)}),this.validDrops=r},getDrop:function(t){var n=!1,r=e.one(t);return r instanceof e.Node&&e.each(this.targets,function(e){r.compareTo(e.get("node"))&&(n=e)}),n}},!0)},"3.7.3",{requires:["dd-ddm"]});
diff --git a/js/yui3/dd-ddm/dd-ddm-min.js b/js/yui3/dd-ddm/dd-ddm-min.js
new file mode 100644
index 000000000..e0a0cad1f
--- /dev/null
+++ b/js/yui3/dd-ddm/dd-ddm-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-ddm",function(e,t){e.mix(e.DD.DDM,{_pg:null,_debugShim:!1,_activateTargets:function(){},_deactivateTargets:function(){},_startDrag:function(){this.activeDrag&&this.activeDrag.get("useShim")&&(this._shimming=!0,this._pg_activate(),this._activateTargets())},_endDrag:function(){this._pg_deactivate(),this._deactivateTargets()},_pg_deactivate:function(){this._pg.setStyle("display","none")},_pg_activate:function(){this._pg||this._createPG();var e=this.activeDrag.get("activeHandle"),t="auto";e&&(t=e.getStyle("cursor")),t==="auto"&&(t=this.get("dragCursor")),this._pg_size(),this._pg.setStyles({top:0,left:0,display:"block",opacity:this._debugShim?".5":"0",cursor:t})},_pg_size:function(){if(this.activeDrag){var t=e.one("body"),n=t.get("docHeight"),r=t.get("docWidth");this._pg.setStyles({height:n+"px",width:r+"px"})}},_createPG:function(){var t=e.Node.create("<div></div>"),n=e.one("body"),r;t.setStyles({top:"0",left:"0",position:"absolute",zIndex:"9999",overflow:"hidden",backgroundColor:"red",display:"none",height:"5px",width:"5px"}),t.set("id",e.stamp(t)),t.addClass(e.DD.DDM.CSS_PREFIX+"-shim"),n.prepend(t),this._pg=t,this._pg.on("mousemove",e.throttle(e.bind(this._move,this),this.get("throttleTime"))),this._pg.on("mouseup",e.bind(this._end,this)),r=e.one("win"),e.on("window:resize",e.bind(this._pg_size,this)),r.on("scroll",e.bind(this._pg_size,this))}},!0)},"3.7.3",{requires:["dd-ddm-base","event-resize"]});
diff --git a/js/yui3/dd-delegate/dd-delegate-min.js b/js/yui3/dd-delegate/dd-delegate-min.js
new file mode 100644
index 000000000..dc9f91224
--- /dev/null
+++ b/js/yui3/dd-delegate/dd-delegate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-delegate",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="container",i="nodes",s=e.Node.create("<div>Temp Node</div>");e.extend(n,e.Base,{_bubbleTargets:e.DD.DDM,dd:null,_shimState:null,_handles:null,_onNodeChange:function(e){this.set("dragNode",e.newVal)},_afterDragEnd:function(){e.DD.DDM._noShim=this._shimState,this.set("lastNode",this.dd.get("node")),this.get("lastNode").removeClass(e.DD.DDM.CSS_PREFIX+"-dragging"),this.dd._unprep(),this.dd.set("node",s)},_delMouseDown:function(t){var n=t.currentTarget,r=this.dd,s=n,o=this.get("dragConfig");n.test(this.get(i))&&!n.test(this.get("invalid"))&&(this._shimState=e.DD.DDM._noShim,e.DD.DDM._noShim=!0,this.set("currentNode",n),r.set("node",n),o&&o.dragNode?s=o.dragNode:r.proxy&&(s=e.DD.DDM._proxy),r.set("dragNode",s),r._prep(),r.fire("drag:mouseDown",{ev:t}))},_onMouseEnter:function(){this._shimState=e.DD.DDM._noShim,e.DD.DDM._noShim=!0},_onMouseLeave:function(){e.DD.DDM._noShim=this._shimState},initializer:function(){this._handles=[];var t=this.get("dragConfig")||{},n=this.get(r);t.node=s.cloneNode(!0),t.bubbleTargets=this,this.get("handles")&&(t.handles=this.get("handles")),this.dd=new e.DD.Drag(t),this.dd.after("drag:end",e.bind(this._afterDragEnd,this)),this.dd.on("dragNodeChange",e.bind(this._onNodeChange,this)),this.dd.after("drag:mouseup",function(){this._unprep()}),this._handles.push(e.delegate(e.DD.Drag.START_EVENT,e.bind(this._delMouseDown,this),n,this.get(i))),this._handles.push(e.on("mouseenter",e.bind(this._onMouseEnter,this),n)),this._handles.push(e.on("mouseleave",e.bind(this._onMouseLeave,this),n)),e.later(50,this,this.syncTargets),e.DD.DDM.regDelegate(this)},syncTargets:function(){if(!e.Plugin.Drop||this.get("destroyed"))return;var t,n,s;return this.get("target")&&(t=e.one(this.get(r)).all(this.get(i)),n=this.dd.get("groups"),s=this.get("dragConfig"),s&&s.groups&&(n=s.groups),t.each(function(e){this.createDrop(e,n)},this)),this},createDrop:function(t,n){var r={useShim:!1,bubbleTargets:this};return t.drop||t.plug(e.Plugin.Drop,r),t.drop.set("groups",n),t},destructor:function(){this.dd&&this.dd.destroy();if(e.Plugin.Drop){var t=e.one(this.get(r)).all(this.get(i));t.unplug(e.Plugin.Drop)}e.each(this._handles,function(e){e.detach()})}},{NAME:"delegate",ATTRS:{container:{value:"body"},nodes:{value:".dd-draggable"},invalid:{value:"input, select, button, a, textarea"},lastNode:{value:s},currentNode:{value:s},dragNode:{value:s},over:{value:!1},target:{value:!1},dragConfig:{value:null},handles:{value:null}}}),e.mix(e.DD.DDM,{_delegates:[],regDelegate:function(e){this._delegates.push(e)},getDelegate:function(t){var n=null;return t=e.one(t),e.each(this._delegates,function(e){t.test(e.get(r))&&(n=e)},this),n}}),e.namespace("DD"),e.DD.Delegate=n},"3.7.3",{requires:["dd-drag","dd-drop-plugin","event-mouseenter"]});
diff --git a/js/yui3/dd-drag/dd-drag-min.js b/js/yui3/dd-drag/dd-drag-min.js
new file mode 100644
index 000000000..6413c409e
--- /dev/null
+++ b/js/yui3/dd-drag/dd-drag-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-drag",function(e,t){var n=e.DD.DDM,r="node",i="dragging",s="dragNode",o="offsetHeight",u="offsetWidth",a="drag:mouseDown",f="drag:afterMouseDown",l="drag:removeHandle",c="drag:addHandle",h="drag:removeInvalid",p="drag:addInvalid",d="drag:start",v="drag:end",m="drag:drag",g="drag:align",y=function(t){this._lazyAddAttrs=!1,y.superclass.constructor.apply(this,arguments);var r=n._regDrag(this);r||e.error("Failed to register node, already in use: "+t.node)};y.NAME="drag",y.START_EVENT="mousedown",y.ATTRS={node:{setter:function(t){if(this._canDrag(t))return t;var n=e.one(t);return n||e.error("DD.Drag: Invalid Node Given: "+t),n}},dragNode:{setter:function(t){if(this._canDrag(t))return t;var n=e.one(t);return n||e.error("DD.Drag: Invalid dragNode Given: "+t),n}},offsetNode:{value:!0},startCentered:{value:!1},clickPixelThresh:{value:n.get("clickPixelThresh")},clickTimeThresh:{value:n.get("clickTimeThresh")},lock:{value:!1,setter:function(e){return e?this.get(r).addClass(n.CSS_PREFIX+"-locked"):this.get(r).removeClass(n.CSS_PREFIX+"-locked"),e}},data:{value:!1},move:{value:!0},useShim:{value:!0},activeHandle:{value:!1},primaryButtonOnly:{value:!0},dragging:{value:!1},parent:{value:!1},target:{value:!1,setter:function(e){return this._handleTarget(e),e}},dragMode:{value:null,setter:function(e){return n._setDragMode(e)}},groups:{value:["default"],getter:function(){this._groups||(this._groups={});var t=[];return e.each(this._groups,function(e,n){t[t.length]=n}),t},setter:function(t){return this._groups={},e.each(t,function(e){this._groups[e]=!0},this),t}},handles:{value:null,setter:function(t){return t?(this._handles={},e.each(t,function(t){var n=t;if(t instanceof e.Node||t instanceof e.NodeList)n=t._yuid;this._handles[n]=t},this)):this._handles=null,t}},bubbles:{setter:function(e){return this.addTarget(e),e}},haltDown:{value:!0}},e.extend(y,e.Base,{_canDrag:function(e){return e&&e.setXY&&e.getXY&&e.test&&e.contains?!0:!1},_bubbleTargets:e.DD.DDM,addToGroup:function(e){return this._groups[e]=!0,n._activateTargets(),this},removeFromGroup:function(e){return delete this._groups[e],n._activateTargets(),this},target:null,_handleTarget:function(t){e.DD.Drop&&(t===!1?this.target&&(n._unregTarget(this.target),this.target=null):(e.Lang.isObject(t)||(t={}),t.bubbleTargets=t.bubbleTargets||e.Object.values(this._yuievt.targets),t.node=this.get(r),t.groups=t.groups||this.get("groups"),this.target=new e.DD.Drop(t)))},_groups:null,_createEvents:function(){this.publish(a,{defaultFn:this._defMouseDownFn,queuable:!1,emitFacade:!0,bubbles:!0,prefix:"drag"}),this.publish(g,{defaultFn:this._defAlignFn,queuable:!1,emitFacade:!0,bubbles:!0,prefix:"drag"}),this.publish(m,{defaultFn:this._defDragFn,queuable:!1,emitFacade:!0,bubbles:!0,prefix:"drag"}),this.publish(v,{defaultFn:this._defEndFn,preventedFn:this._prevEndFn,queuable:!1,emitFacade:!0,bubbles:!0,prefix:"drag"});var t=[f,l,c,h,p,d,"drag:drophit","drag:dropmiss","drag:over","drag:enter","drag:exit"];e.each(t,function(e){this.publish(e,{type:e,emitFacade:!0,bubbles:!0,preventable:!1,queuable:!1,prefix:"drag"})},this)},_ev_md:null,_startTime:null,_endTime:null,_handles:null,_invalids:null,_invalidsDefault:{textarea:!0,input:!0,a:!0,button:!0,select:!0},_dragThreshMet:null,_fromTimeout:null,_clickTimeout:null,deltaXY:null,startXY:null,nodeXY:null,lastXY:null,actXY:null,realXY:null,mouseXY:null,region:null,_handleMouseUp:function(){this.fire("drag:mouseup"),this._fixIEMouseUp(),n.activeDrag&&n._end()},_fixDragStart:function(e){this.validClick(e)&&e.preventDefault()},_ieSelectFix:function(){return!1},_ieSelectBack:null,_fixIEMouseDown:function(){e.UA.ie&&(this._ieSelectBack=e.config.doc.body.onselectstart,e.config.doc.body.onselectstart=this._ieSelectFix)},_fixIEMouseUp:function(){e.UA.ie&&(e.config.doc.body.onselectstart=this._ieSelectBack)},_handleMouseDownEvent:function(e){this.fire(a,{ev:e})},_defMouseDownFn:function(t){var r=t.ev;this._dragThreshMet=!1,this._ev_md=r;if(this.get("primaryButtonOnly")&&r.button>1)return!1;this.validClick(r)&&(this._fixIEMouseDown(r),y.START_EVENT.indexOf("gesture")!==0&&(this.get("haltDown")?r.halt():r.preventDefault()),this._setStartPosition([r.pageX,r.pageY]),n.activeDrag=this,this._clickTimeout=e.later(this.get("clickTimeThresh"),this,this._timeoutCheck)),this.fire(f,{ev:r})},validClick:function(t){var n=!1,i=!1,s=t.target,o=null,u=null,a=null,f=!1;if(this._handles)e.each(this._handles,function(t,r){t instanceof e.Node||t instanceof e.NodeList?n||(a=t,a instanceof e.Node&&(a=new e.NodeList(t._node)),a.each(function(e){e.contains(s)&&(n=!0)})):e.Lang.isString(r)&&s.test(r+", "+r+" *")&&!o&&(o=r,n=!0)});else{i=this.get(r);if(i.contains(s)||i.compareTo(s))n=!0}return n&&this._invalids&&e.each(this._invalids,function(t,r){e.Lang.isString(r)&&s.test(r+", "+r+" *")&&(n=!1)}),n&&(o?(u=t.currentTarget.all(o),f=!1,u.each(function(e){(e.contains(s)||e.compareTo(s))&&!f&&(f=!0,this.set("activeHandle",e))},this)):this.set("activeHandle",this.get(r))),n},_setStartPosition:function(e){this.startXY=e,this.nodeXY=this.lastXY=this.realXY=this.get(r).getXY(),this.get("offsetNode")?this.deltaXY=[this.startXY[0]-this.nodeXY[0],this.startXY[1]-this.nodeXY[1]]:this.deltaXY=[0,0]},_timeoutCheck:function(){!this.get("lock")&&!this._dragThreshMet&&this._ev_md&&(this._fromTimeout=this._dragThreshMet=!0,this.start(),this._alignNode([this._ev_md.pageX,this._ev_md.pageY],!0))},removeHandle:function(t){var n=t;if(t instanceof e.Node||t instanceof e.NodeList)n=t._yuid;return this._handles[n]&&(delete this._handles[n],this.fire(l,{handle:t})),this},addHandle:function(t){this._handles||(this._handles={});var n=t;if(t instanceof e.Node||t instanceof e.NodeList)n=t._yuid;return this._handles[n]=t,this.fire(c,{handle:t}),this},removeInvalid:function(e){return this._invalids[e]&&(this._invalids[e]=null,delete this._invalids[e],this.fire(h,{handle:e})),this},addInvalid:function(t){return e.Lang.isString(t)&&(this._invalids[t]=!0,this.fire(p,{handle:t})),this},initializer:function(){this.get(r).dd=this;if(!this.get(r).get("id")){var t=e.stamp(this.get(r));this.get(r).set("id",t)}this.actXY=[],this._invalids=e.clone(this._invalidsDefault,!0),this._createEvents(),this.get(s)||this.set(s,this.get(r)),this.on("initializedChange",e.bind(this._prep,this)),this.set("groups",this.get("groups"))},_prep:function(){this._dragThreshMet=!1;var t=this.get(r);t.addClass(n.CSS_PREFIX+"-draggable"),t.on(y.START_EVENT,e.bind(this._handleMouseDownEvent,this)),t.on("mouseup",e.bind(this._handleMouseUp,this)),t.on("dragstart",e.bind(this._fixDragStart,this))},_unprep:function(){var e=this.get(r);e.removeClass(n.CSS_PREFIX+"-draggable"),e.detachAll("mouseup"),e.detachAll("dragstart"),e.detachAll(y.START_EVENT),this.mouseXY=[],this.deltaXY=[0,0],this.startXY=[],this.nodeXY=[],this.lastXY=[],this.actXY=[],this.realXY=[]},start:function(){if(!this.get("lock")&&!this.get(i)){var e=this.get(r),t,a,f;this._startTime=(new Date).getTime(),n._start(),e.addClass(n.CSS_PREFIX+"-dragging"),this.fire(d,{pageX:this.nodeXY[0],pageY:this.nodeXY[1],startTime:this._startTime}),e=this.get(s),f=this.nodeXY,t=e.get(u),a=e.get(o),this.get("startCentered")&&this._setStartPosition([f[0]+t/2,f[1]+a/2]),this.region={0:f[0],1:f[1],area:0,top:f[1],right:f[0]+t,bottom:f[1]+a,left:f[0]},this.set(i,!0)}return this},end:function(){return this._endTime=(new Date).getTime(),this._clickTimeout&&this._clickTimeout.cancel(),this._dragThreshMet=this._fromTimeout=!1,!this.get("lock")&&this.get(i)&&this.fire(v,{pageX:this.lastXY[0],pageY:this.lastXY[1],startTime:this._startTime,endTime:this._endTime}),this.get(r).removeClass(n.CSS_PREFIX+"-dragging"),this.set(i,!1),this.deltaXY=[0,0],this},_defEndFn:function(){this._fixIEMouseUp(),this._ev_md=null},_prevEndFn:function(){this._fixIEMouseUp(),this.get(s).setXY(this.nodeXY),this._ev_md=null,this.region=null},_align:function(e){this.fire(g,{pageX:e[0],pageY:e[1]})},_defAlignFn:function(e){this.actXY=[e.pageX-this.deltaXY[0],e.pageY-this.deltaXY[1]]},_alignNode:function(e,t){this._align(e),t||this._moveNode()},_moveNode:function(e){var t=[],n=[],r=this.nodeXY,i=this.actXY;t[0]=i[0]-this.lastXY[0],t[1]=i[1]-this.lastXY[1],n[0]=i[0]-this.nodeXY[0],n[1]=i[1]-this.nodeXY[1],this.region={0:i[0],1:i[1],area:0,top:i[1],right:i[0]+this.get(s).get(u),bottom:i[1]+this.get(s).get(o),left:i[0]},this.fire(m,{pageX:i[0],pageY:i[1],scroll:e,info:{start:r,xy:i,delta:t,offset:n}}),this.lastXY=i},_defDragFn:function(e){this.get("move")&&(e.scroll&&e.scroll.node&&(e.scroll.node.set("scrollTop",e.scroll.top),e.scroll.node.set("scrollLeft",e.scroll.left)),this.get(s).setXY([e.pageX,e.pageY]),this.realXY=[e.pageX,e.pageY])},_move:function(e){if(this.get("lock"))return!1;this.mouseXY=[e.pageX,e.pageY];if(!this._dragThreshMet){var t=Math.abs(this.startXY[0]-e.pageX),n=Math.abs(this.startXY[1]-e.pageY);if(t>this.get("clickPixelThresh")||n>this.get("clickPixelThresh"))this._dragThreshMet=!0,this.start(),e&&e.preventDefault&&e.preventDefault(),this._alignNode([e.pageX,e.pageY])}else this._clickTimeout&&this._clickTimeout.cancel(),this._alignNode([e.pageX,e.pageY])},stopDrag:function(){return this.get(i)&&n._end(),this},destructor:function(){this._unprep(),this.target&&this.target.destroy(),n._unregDrag(this)}}),e.namespace("DD"),e.DD.Drag=y},"3.7.3",{requires:["dd-ddm-base"]});
diff --git a/js/yui3/dd-drop-plugin/dd-drop-plugin-min.js b/js/yui3/dd-drop-plugin/dd-drop-plugin-min.js
new file mode 100644
index 000000000..0b4640dc0
--- /dev/null
+++ b/js/yui3/dd-drop-plugin/dd-drop-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-drop-plugin",function(e,t){var n=function(e){e.node=e.host,n.superclass.constructor.apply(this,arguments)};n.NAME="dd-drop-plugin",n.NS="drop",e.extend(n,e.DD.Drop),e.namespace("Plugin"),e.Plugin.Drop=n},"3.7.3",{requires:["dd-drop"]});
diff --git a/js/yui3/dd-drop/dd-drop-min.js b/js/yui3/dd-drop/dd-drop-min.js
new file mode 100644
index 000000000..3aaf6e974
--- /dev/null
+++ b/js/yui3/dd-drop/dd-drop-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-drop",function(e,t){var n="node",r=e.DD.DDM,i="offsetHeight",s="offsetWidth",o="drop:over",u="drop:enter",a="drop:exit",f=function(){this._lazyAddAttrs=!1,f.superclass.constructor.apply(this,arguments),e.on("domready",e.bind(function(){e.later(100,this,this._createShim)},this)),r._regTarget(this)};f.NAME="drop",f.ATTRS={node:{setter:function(t){var n=e.one(t);return n||e.error("DD.Drop: Invalid Node Given: "+t),n}},groups:{value:["default"],getter:function(){this._groups||(this._groups={});var t=[];return e.each(this._groups,function(e,n){t[t.length]=n}),t},setter:function(t){return this._groups={},e.each(t,function(e){this._groups[e]=!0},this),t}},padding:{value:"0",setter:function(e){return r.cssSizestoObject(e)}},lock:{value:!1,setter:function(e){return e?this.get(n).addClass(r.CSS_PREFIX+"-drop-locked"):this.get(n).removeClass(r.CSS_PREFIX+"-drop-locked"),e}},bubbles:{setter:function(e){return this.addTarget(e),e}},useShim:{value:!0,setter:function(t){return e.DD.DDM._noShim=!t,t}}},e.extend(f,e.Base,{_bubbleTargets:e.DD.DDM,addToGroup:function(e){return this._groups[e]=!0,this},removeFromGroup:function(e){return delete this._groups[e],this},_createEvents:function(){var t=[o,u,a,"drop:hit"];e.each(t,function(e){this.publish(e,{type:e,emitFacade:!0,preventable:!1,bubbles:!0,queuable:!1,prefix:"drop"})},this)},_valid:null,_groups:null,shim:null,region:null,overTarget:null,inGroup:function(t){this._valid=!1;var n=!1;return e.each(t,function(e){this._groups[e]&&(n=!0,this._valid=!0)},this),n},initializer:function(){e.later(100,this,this._createEvents);var t=this.get(n),i;t.get("id")||(i=e.stamp(t),t.set("id",i)),t.addClass(r.CSS_PREFIX+"-drop"),this.set("groups",this.get("groups"))},destructor:function(){r._unregTarget(this),this.shim&&this.shim!==this.get(n)&&(this.shim.detachAll(),this.shim.remove(),this.shim=null),this.get(n).removeClass(r.CSS_PREFIX+"-drop"),this.detachAll()},_deactivateShim:function(){if(!this.shim)return!1;this.get(n).removeClass(r.CSS_PREFIX+"-drop-active-valid"),this.get(n).removeClass(r.CSS_PREFIX+"-drop-active-invalid"),this.get(n).removeClass(r.CSS_PREFIX+"-drop-over"),this.get("useShim")&&this.shim.setStyles({top:"-999px",left:"-999px",zIndex:"1"}),this.overTarget=!1},_activateShim:function(){if(!r.activeDrag)return!1;if(this.get(n)===r.activeDrag.get(n))return!1;if(this.get("lock"))return!1;var e=this.get(n);this.inGroup(r.activeDrag.get("groups"))?(e.removeClass(r.CSS_PREFIX+"-drop-active-invalid"),e.addClass(r.CSS_PREFIX+"-drop-active-valid"),r._addValid(this),this.overTarget=!1,this.get("useShim")||(this.shim=this.get(n)),this.sizeShim()):(r._removeValid(this),e.removeClass(r.CSS_PREFIX+"-drop-active-valid"),e.addClass(r.CSS_PREFIX+"-drop-active-invalid"))},sizeShim:function(){if(!r.activeDrag)return!1;if(this.get(n)===r.activeDrag.get(n))return!1;if(this.get("lock"))return!1;if(!this.shim)return e.later(100,this,this.sizeShim),!1;var t=this.get(n),o=t.get(i),u=t.get(s),a=t.getXY(),f=this.get("padding"),l,c,h;u=u+f.left+f.right,o=o+f.top+f.bottom,a[0]=a[0]-f.left,a[1]=a[1]-f.top,r.activeDrag.get("dragMode")===r.INTERSECT&&(l=r.activeDrag,c=l.get(n).get(i),h=l.get(n).get(s),o+=c,u+=h,a[0]=a[0]-(h-l.deltaXY[0]),a[1]=a[1]-(c-l.deltaXY[1])),this.get("useShim")&&this.shim.setStyles({height:o+"px",width:u+"px",top:a[1]+"px",left:a[0]+"px"}),this.region={0:a[0],1:a[1],area:0,top:a[1],right:a[0]+u,bottom:a[1]+o,left:a[0]}},_createShim:function(){if(!r._pg){e.later(10,this,this._createShim);return}if(this.shim)return;var t=this.get("node");this.get("useShim")&&(t=e.Node.create('<div id="'+this.get(n).get("id")+'_shim"></div>'),t.setStyles({height:this.get(n).get(i)+"px",width:this.get(n).get(s)+"px",backgroundColor:"yellow",opacity:".5",zIndex:"1",overflow:"hidden",top:"-900px",left:"-900px",position:"absolute"}),r._pg.appendChild(t),t.on("mouseover",e.bind(this._handleOverEvent,this)),t.on("mouseout",e.bind(this._handleOutEvent,this))),this.shim=t},_handleTargetOver:function(){r.isOverTarget(this)?(this.get(n).addClass(r.CSS_PREFIX+"-drop-over"),r.activeDrop=this,r.otherDrops[this]=this,this.overTarget?(r.activeDrag.fire("drag:over",{drop:this,drag:r.activeDrag}),this.fire(o,{drop:this,drag:r.activeDrag})):r.activeDrag.get("dragging")&&(this.overTarget=!0,this.fire(u,{drop:this,drag:r.activeDrag}),r.activeDrag.fire("drag:enter",{drop:this,drag:r.activeDrag}),r.activeDrag.get(n).addClass(r.CSS_PREFIX+"-drag-over"))):this._handleOut()},_handleOverEvent:function(){this.shim.setStyle("zIndex","999"),r._addActiveShim(this)},_handleOutEvent:function(){this.shim.setStyle("zIndex","1"),r._removeActiveShim(this)},_handleOut:function(e){(!r.isOverTarget(this)||e)&&this.overTarget&&(this.overTarget=!1,e||r._removeActiveShim(this),r.activeDrag&&(this.get(n).removeClass(r.CSS_PREFIX+"-drop-over"),r.activeDrag.get(n).removeClass(r.CSS_PREFIX+"-drag-over"),this.fire(a,{drop:this,drag:r.activeDrag}),r.activeDrag.fire("drag:exit",{drop:this,drag:r.activeDrag}),delete r.otherDrops[this]))}}),e.DD.Drop=f},"3.7.3",{requires:["dd-drag","dd-ddm-drop"]});
diff --git a/js/yui3/dd-gestures/dd-gestures-min.js b/js/yui3/dd-gestures/dd-gestures-min.js
new file mode 100644
index 000000000..fb608ac0b
--- /dev/null
+++ b/js/yui3/dd-gestures/dd-gestures-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-gestures",function(e,t){e.DD.Drag.START_EVENT="gesturemovestart",e.DD.Drag.prototype._prep=function(){this._dragThreshMet=!1;var t=this.get("node"),n=e.DD.DDM;t.addClass(n.CSS_PREFIX+"-draggable"),t.on(e.DD.Drag.START_EVENT,e.bind(this._handleMouseDownEvent,this),{minDistance:this.get("clickPixelThresh"),minTime:this.get("clickTimeThresh")}),t.on("gesturemoveend",e.bind(this._handleMouseUp,this),{standAlone:!0}),t.on("dragstart",e.bind(this._fixDragStart,this))};var n=e.DD.Drag.prototype._unprep;e.DD.Drag.prototype._unprep=function(){var e=this.get("node");n.call(this),e.detachAll("gesturemoveend")},e.DD.DDM._setupListeners=function(){var t=e.DD.DDM;this._createPG(),this._active=!0,e.one(e.config.doc).on("gesturemove",e.throttle(e.bind(t._move,t),t.get("throttleTime")),{standAlone:!0})}},"3.7.3",{requires:["dd-drag","event-synthetic","event-gestures"]});
diff --git a/js/yui3/dd-plugin/dd-plugin-min.js b/js/yui3/dd-plugin/dd-plugin-min.js
new file mode 100644
index 000000000..645ae78dc
--- /dev/null
+++ b/js/yui3/dd-plugin/dd-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-plugin",function(e,t){var n=function(t){e.Widget&&t.host instanceof e.Widget?(t.node=t.host.get("boundingBox"),t.widget=t.host):(t.node=t.host,t.widget=!1),n.superclass.constructor.call(this,t)},r="drag:start",i="drag:drag",s="drag:end";n.NAME="dd-plugin",n.NS="dd",e.extend(n,e.DD.Drag,{_widgetHandles:null,_widget:undefined,_stoppedPosition:undefined,_usesWidgetPosition:function(t){var n=!1;return t&&(n=t.hasImpl&&t.hasImpl(e.WidgetPosition)?!0:!1),n},_checkEvents:function(){this._widget&&(this.proxy?this._widgetHandles.length>0&&this._removeWidgetListeners():this._widgetHandles.length===0&&this._attachWidgetListeners())},_removeWidgetListeners:function(){e.Array.each(this._widgetHandles,function(e){e.detach()}),this._widgetHandles=[]},_attachWidgetListeners:function(){this._usesWidgetPosition(this._widget)&&(this._widgetHandles.push(this.on(i,this._setWidgetCoords)),this._widgetHandles.push(this.on(s,this._updateStopPosition)))},initializer:function(e){this._widgetHandles=[],this._widget=e.widget,this.on(r,this._checkEvents),this._attachWidgetListeners()},_setWidgetCoords:function(e){var t=this._stoppedPosition||e.target.nodeXY,n=e.target.realXY,r=[n[0]-t[0],n[1]-t[1]];r[0]!==0&&r[1]!==0?this._widget.set("xy",n):r[0]===0?this._widget.set("y",n[1]):r[1]===0&&this._widget.set("x",n[0])},_updateStopPosition:function(e){this._stoppedPosition=e.target.realXY}}),e.namespace("Plugin"),e.Plugin.Drag=n},"3.7.3",{optional:["dd-constrain","dd-proxy"],requires:["dd-drag"]});
diff --git a/js/yui3/dd-proxy/dd-proxy-min.js b/js/yui3/dd-proxy/dd-proxy-min.js
new file mode 100644
index 000000000..b3234d868
--- /dev/null
+++ b/js/yui3/dd-proxy/dd-proxy-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-proxy",function(e,t){var n=e.DD.DDM,r="node",i="dragNode",s="host",o=!0,u,a=function(){a.superclass.constructor.apply(this,arguments)};a.NAME="DDProxy",a.NS="proxy",a.ATTRS={host:{},moveOnEnd:{value:o},hideOnEnd:{value:o},resizeFrame:{value:o},positionProxy:{value:o},borderStyle:{value:"1px solid #808080"},cloneNode:{value:!1}},u={_hands:null,_init:function(){if(!n._proxy){n._createFrame(),e.on("domready",e.bind(this._init,this));return}this._hands||(this._hands=[]);var t,o,u=this.get(s),a=u.get(i);a.compareTo(u.get(r))&&n._proxy&&u.set(i,n._proxy),e.each(this._hands,function(e){e.detach()}),t=n.on("ddm:start",e.bind(function(){n.activeDrag===u&&n._setFrame(u)},this)),o=n.on("ddm:end",e.bind(function(){u.get("dragging")&&(this.get("moveOnEnd")&&u.get(r).setXY(u.lastXY),this.get("hideOnEnd")&&u.get(i).setStyle("display","none"),this.get("cloneNode")&&(u.get(i).remove(),u.set(i,n._proxy)))},this)),this._hands=[t,o]},initializer:function(){this._init()},destructor:function(){var t=this.get(s);e.each(this._hands,function(e){e.detach()}),t.set(i,t.get(r))},clone:function(){var t=this.get(s),n=t.get(r),o=n.cloneNode(!0);return delete o._yuid,o.setAttribute("id",e.guid()),o.setStyle("position","absolute"),n.get("parentNode").appendChild(o),t.set(i,o),o}},e.namespace("Plugin"),e.extend(a,e.Base,u),e.Plugin.DDProxy=a,e.mix(n,{_createFrame:function(){if(!n._proxy){n._proxy=o;var t=e.Node.create("<div></div>"),r=e.one("body");t.setStyles({position:"absolute",display:"none",zIndex:"999",top:"-999px",left:"-999px"}),r.prepend(t),t.set("id",e.guid()),t.addClass(n.CSS_PREFIX+"-proxy"),n._proxy=t}},_setFrame:function(e){var t=e.get(r),s=e.get(i),o,u="auto";o=n.activeDrag.get("activeHandle"),o&&(u=o.getStyle("cursor")),u==="auto"&&(u=n.get("dragCursor")),s.setStyles({visibility:"hidden",display:"block",cursor:u,border:e.proxy.get("borderStyle")}),e.proxy.get("cloneNode")&&(s=e.proxy.clone()),e.proxy.get("resizeFrame")&&s.setStyles({height:t.get("offsetHeight")+"px",width:t.get("offsetWidth")+"px"}),e.proxy.get("positionProxy")&&s.setXY(e.nodeXY),s.setStyle("visibility","visible")}})},"3.7.3",{requires:["dd-drag"]});
diff --git a/js/yui3/dd-scroll/dd-scroll-min.js b/js/yui3/dd-scroll/dd-scroll-min.js
new file mode 100644
index 000000000..df0609457
--- /dev/null
+++ b/js/yui3/dd-scroll/dd-scroll-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dd-scroll",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r,i,s="host",o="buffer",u="parentScroll",a="windowScroll",f="scrollTop",l="scrollLeft",c="offsetWidth",h="offsetHeight";n.ATTRS={parentScroll:{value:!1,setter:function(e){return e?e:!1}},buffer:{value:30,validator:e.Lang.isNumber},scrollDelay:{value:235,validator:e.Lang.isNumber},host:{value:null},windowScroll:{value:!1,validator:e.Lang.isBoolean},vertical:{value:!0,validator:e.Lang.isBoolean},horizontal:{value:!0,validator:e.Lang.isBoolean}},e.extend(n,e.Base,{_scrolling:null,_vpRegionCache:null,_dimCache:null,_scrollTimer:null,_getVPRegion:function(){var e={},t=this.get(u),n=this.get(o),r=this.get(a),i=r?[]:t.getXY(),s=r?"winWidth":c,p=r?"winHeight":h,d=r?t.get(f):i[1],v=r?t.get(l):i[0];return e={top:d+n,right:t.get(s)+v-n,bottom:t.get(p)+d-n,left:v+n},this._vpRegionCache=e,e},initializer:function(){var t=this.get(s);t.after("drag:start",e.bind(this.start,this)),t.after("drag:end",e.bind(this.end,this)),t.on("drag:align",e.bind(this.align,this)),e.one("win").on("scroll",e.bind(function(){this._vpRegionCache=null},this))},_checkWinScroll:function(e){var t=this._getVPRegion(),n=this.get(s),r=this.get(a),i=n.lastXY,c=!1,h=this.get(o),p=this.get(u),d=p.get(f),v=p.get(l),m=this._dimCache.w,g=this._dimCache.h,y=i[1]+g,b=i[1],w=i[0]+m,E=i[0],S=b,x=E,T=d,N=v;this.get("horizontal")&&(E<=t.left&&(c=!0,x=i[0]-(r?h:0),N=v-h),w>=t.right&&(c=!0,x=i[0]+(r?h:0),N=v+h)),this.get("vertical")&&(y>=t.bottom&&(c=!0,S=i[1]+(r?h:0),T=d+h),b<=t.top&&(c=!0,S=i[1]-(r?h:0),T=d-h)),T<0&&(T=0,S=i[1]),N<0&&(N=0,x=i[0]),S<0&&(S=i[1]),x<0&&(x=i[0]),n.con&&(n.con.inRegion([x+N,S+T])||(e=!1)),e?(n.actXY=[x,S],n._alignNode([x,S],!0),i=n.actXY,n.actXY=[x,S],n._moveNode({node:p,top:T,left:N}),!T&&!N&&this._cancelScroll()):c?this._initScroll():this._cancelScroll()},_initScroll:function(){this._cancelScroll(),this._scrollTimer=e.Lang.later(this.get("scrollDelay"),this,this._checkWinScroll,[!0],!0)},_cancelScroll:function(){this._scrolling=!1,this._scrollTimer&&(this._scrollTimer.cancel(),delete this._scrollTimer)},align:function(e){this._scrolling&&(this._cancelScroll(),e.preventDefault()),this._scrolling||this._checkWinScroll()},_setDimCache:function(){var e=this.get(s).get("dragNode");this._dimCache={h:e.get(h),w:e.get(c)}},start:function(){this._setDimCache()},end:function(){this._dimCache=null,this._cancelScroll()}}),e.namespace("Plugin"),r=function(){r.superclass.constructor.apply(this,arguments)},r.ATTRS=e.merge(n.ATTRS,{windowScroll:{value:!0,setter:function(t){return t&&this.set(u,e.one("win")),t}}}),e.extend(r,n,{initializer:function(){this.set("windowScroll",this.get("windowScroll"))}}),r.NAME=r.NS="winscroll",e.Plugin.DDWinScroll=r,i=function(){i.superclass.constructor.apply(this,arguments)},i.ATTRS=e.merge(n.ATTRS,{node:{value:!1,setter:function(t){var n=e.one(t);return n?this.set(u,n):t!==!1&&e.error("DDNodeScroll: Invalid Node Given: "+t),n}}}),e.extend(i,n,{initializer:function(){this.set("node",this.get("node"))}}),i.NAME=i.NS="nodescroll",e.Plugin.DDNodeScroll=i,e.DD.Scroll=n},"3.7.3",{requires:["dd-drag"]});
diff --git a/js/yui3/dial/assets/dial-core.css b/js/yui3/dial/assets/dial-core.css
new file mode 100644
index 000000000..84bf14e34
--- /dev/null
+++ b/js/yui3/dial/assets/dial-core.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+v\:oval,
+v\:shadow,
+v\:fill {
+ behavior: url(#default#VML);
+ display: inline-block;
+ zoom: 1; *display: inline; /* IE < 8: fake inline-block */
+}
+.yui3-dial{
+ position:relative;
+ display:-moz-inline-stack;
+ display:inline-block;
+ zoom:1;
+ *display:inline;
+ /*text-align:center; This causes problems with the angle calc with longer labels*/
+}
+.yui3-dial-content,
+.yui3-dial-ring{
+ position:relative;
+}
+.yui3-dial-handle,
+.yui3-dial-marker,
+.yui3-dial-center-button,
+.yui3-dial-reset-string,
+.yui3-dial-handle-vml,
+.yui3-dial-marker-vml,
+.yui3-dial-center-button-vml,
+.yui3-dial-ring-vml v\:oval,
+.yui3-dial-center-button-vml v\:oval
+{
+ position:absolute;
+}
+.yui3-dial-center-button-vml v\:oval {
+ font-size:1px;
+ top:0;
+ left:0;
+}
+.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden v\:oval,
+.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden {
+ /* [#2530206] using opacity instead of display:none;. display:none was mis-positioning the marker when we set the dial value on ring mousedown. */
+ opacity:0;
+ filter:alpha(opacity=0);
+}
diff --git a/js/yui3/dial/assets/skins/night/dial.css b/js/yui3/dial/assets/skins/night/dial.css
new file mode 100644
index 000000000..3b41bcb08
--- /dev/null
+++ b/js/yui3/dial/assets/skins/night/dial.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+v\:oval,v\:shadow,v\:fill{behavior:url(#default#VML);display:inline-block;zoom:1;*display:inline}.yui3-dial{position:relative;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.yui3-dial-content,.yui3-dial-ring{position:relative}.yui3-dial-handle,.yui3-dial-marker,.yui3-dial-center-button,.yui3-dial-reset-string,.yui3-dial-handle-vml,.yui3-dial-marker-vml,.yui3-dial-center-button-vml,.yui3-dial-ring-vml v\:oval,.yui3-dial-center-button-vml v\:oval{position:absolute}.yui3-dial-center-button-vml v\:oval{font-size:1px;top:0;left:0}.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden v\:oval,.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden{opacity:0;filter:alpha(opacity=0)}.yui3-skin-night .yui3-dial{color:#fff}.yui3-skin-night .yui3-dial-handle{background:#439ede;opacity:.3;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;cursor:pointer;font-size:1px}.yui3-skin-night .yui3-dial-ring{background:#595b5b;background:-moz-linear-gradient(0% 100% 315deg,#5e6060,#2d2e2f);background:-webkit-gradient(linear,50% 0,100% 100%,from(#636666),to(#424344));-moz-box-shadow:1px 1px 2px rgba(0,0,0,0.7) inset;-webkit-box-shadow:1px 1px 3px rgba(0,0,0,0.7) inset;box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset}.yui3-skin-night .yui3-dial-center-button{-moz-box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);-webkit-box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);background:#dddbd4;background:-moz-radial-gradient(30% 30% 0deg,circle farthest-side,#999c9c 24%,#898989 41%,#535555 87%) repeat scroll 0 0 transparent;background:-webkit-gradient(radial,15 15,15,30 30,40,from(#999c9c),to(#535555),color-stop(.2,#898989));cursor:pointer;opacity:.7}.yui3-skin-night .yui3-dial-reset-string{color:#fff;font-size:72%;text-decoration:none}.yui3-skin-night .yui3-dial-label{color:#cbcbcb;margin-bottom:.8em}.yui3-skin-night .yui3-dial-value-string{margin-left:.5em;color:#dcdcdc;font-size:130%}.yui3-skin-night .yui3-dial-value{visibility:hidden;position:absolute;top:0;left:102%;width:4em}.yui3-skin-night .yui3-dial-north-mark{position:absolute;border-left:2px solid #434343;height:5px;left:50%;top:-7px;font-size:1px}.yui3-skin-night .yui3-dial-marker{background-color:#a0d8ff;opacity:.2;font-size:1px}.yui3-skin-night .yui3-dial-marker-max-min{background-color:#ff0404;opacity:.6}.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}#yui3-css-stamp.skin-night-dial{display:none}
diff --git a/js/yui3/dial/assets/skins/sam/dial.css b/js/yui3/dial/assets/skins/sam/dial.css
new file mode 100644
index 000000000..de135759e
--- /dev/null
+++ b/js/yui3/dial/assets/skins/sam/dial.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+v\:oval,v\:shadow,v\:fill{behavior:url(#default#VML);display:inline-block;zoom:1;*display:inline}.yui3-dial{position:relative;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.yui3-dial-content,.yui3-dial-ring{position:relative}.yui3-dial-handle,.yui3-dial-marker,.yui3-dial-center-button,.yui3-dial-reset-string,.yui3-dial-handle-vml,.yui3-dial-marker-vml,.yui3-dial-center-button-vml,.yui3-dial-ring-vml v\:oval,.yui3-dial-center-button-vml v\:oval{position:absolute}.yui3-dial-center-button-vml v\:oval{font-size:1px;top:0;left:0}.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden v\:oval,.yui3-dial-content .yui3-dial-ring .yui3-dial-hidden{opacity:0;filter:alpha(opacity=0)}.yui3-skin-sam .yui3-dial-handle{background:#6c3a3a;opacity:.3;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.9) inset;cursor:pointer;font-size:1px}.yui3-skin-sam .yui3-dial-ring{background:#bebdb7;background:-moz-linear-gradient(100% 100% 135deg,#7b7a6d,#fff);background:-webkit-gradient(linear,left top,right bottom,from(#fff),to(#7b7a6d));box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-webkit-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset;-moz-box-shadow:1px 1px 5px rgba(0,0,0,0.4) inset}.yui3-skin-sam .yui3-dial-center-button{box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);-moz-box-shadow:-1px -1px 2px rgba(0,0,0,0.3) inset,1px 1px 2px rgba(0,0,0,0.5);background:#dddbd4;background:-moz-radial-gradient(30% 30% 0deg,circle farthest-side,#fbfbf9 24%,#f2f0ea 41%,#d3d0c3 83%) repeat scroll 0 0 transparent;background:-webkit-gradient(radial,15 15,15,30 30,40,from(#fbfbf9),to(#d3d0c3),color-stop(.2,#f2f0ea));cursor:pointer;opacity:.7}.yui3-skin-sam .yui3-dial-reset-string{color:#676767;font-size:85%;text-decoration:underline}.yui3-skin-sam .yui3-dial-label{color:#808080;margin-bottom:.8em}.yui3-skin-sam .yui3-dial-value-string{margin-left:.5em;color:#000;font-size:130%}.yui3-skin-sam .yui3-dial-value{visibility:hidden;position:absolute;top:0;left:102%;width:4em}.yui3-skin-sam .yui3-dial-north-mark{position:absolute;border-left:2px solid #ccc;height:5px;width:10px;left:50%;top:-7px;font-size:1px}.yui3-skin-sam .yui3-dial-marker{background-color:#000;opacity:.2;font-size:1px}.yui3-skin-sam .yui3-dial-marker-max-min{background-color:#ab3232;opacity:.6}.yui3-skin-sam .yui3-dial-ring-vml,.yui3-skin-sam .yui3-dial-center-button-vml,.yui3-skin-sam .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam v\:oval.yui3-dial-marker-max-min,.yui3-skin-sam .yui3-dial-marker-vml,.yui3-skin-sam .yui3-dial-handle-vml{background:0;opacity:1}#yui3-css-stamp.skin-sam-dial{display:none}
diff --git a/js/yui3/dial/dial-min.js b/js/yui3/dial/dial-min.js
new file mode 100644
index 000000000..91877f036
--- /dev/null
+++ b/js/yui3/dial/dial-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dial",function(e,t){function o(e){o.superclass.constructor.apply(this,arguments)}function u(t){return e.ClassNameManager.getClassName(o.NAME,t)}var n=!1;e.UA.ie&&e.UA.ie<9&&(n=!0);var r=e.Lang,i=e.Widget,s=e.Node;o.NAME="dial",o.ATTRS={min:{value:-220},max:{value:220},diameter:{value:100},handleDiameter:{value:.2},markerDiameter:{value:.1},centerButtonDiameter:{value:.5},value:{value:0,validator:function(e){return this._validateValue(e)}},minorStep:{value:1},majorStep:{value:10},stepsPerRevolution:{value:100},decimalPlaces:{value:0},strings:{valueFn:function(){return e.Intl.get("dial")}},handleDistance:{value:.75}},o.CSS_CLASSES={label:u("label"),labelString:u("label-string"),valueString:u("value-string"),northMark:u("north-mark"),ring:u("ring"),ringVml:u("ring-vml"),marker:u("marker"),markerVml:u("marker-vml"),markerMaxMin:u("marker-max-min"),centerButton:u("center-button"),centerButtonVml:u("center-button-vml"),resetString:u("reset-string"),handle:u("handle"),handleVml:u("handle-vml"),hidden:u("hidden"),dragging:e.ClassNameManager.getClassName("dd-dragging")},o.LABEL_TEMPLATE='<div class="'+o.CSS_CLASSES.label+'"><span id="" class="'+o.CSS_CLASSES.labelString+'">{label}</span><span class="'+o.CSS_CLASSES.valueString+'"></span></div>',n===!1?(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+'"><div class="'+o.CSS_CLASSES.northMark+'"></div></div>',o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.marker+" "+o.CSS_CLASSES.hidden+'"></div>',o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+'"><div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div></div>',o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handle+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'):(o.RING_TEMPLATE='<div class="'+o.CSS_CLASSES.ring+" "+o.CSS_CLASSES.ringVml+'">'+'<div class="'+o.CSS_CLASSES.northMark+'"></div>'+'<v:oval strokecolor="#ceccc0" strokeweight="1px"><v:fill type=gradient color="#8B8A7F" color2="#EDEDEB" angle="45"/></v:oval>'+"</div>"+"",o.MARKER_TEMPLATE='<div class="'+o.CSS_CLASSES.markerVml+" "+o.CSS_CLASSES.hidden+'">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#000"/>'+"</v:oval>"+"</div>"+"",o.CENTER_BUTTON_TEMPLATE='<div class="'+o.CSS_CLASSES.centerButton+" "+o.CSS_CLASSES.centerButtonVml+'">'+'<v:oval strokecolor="#ceccc0" strokeweight="1px">'+'<v:fill type=gradient color="#C7C5B9" color2="#fefcf6" colors="35% #d9d7cb, 65% #fefcf6" angle="45"/>'+'<v:shadow on="True" color="#000" opacity="10%" offset="2px, 2px"/>'+"</v:oval>"+'<div class="'+o.CSS_CLASSES.resetString+" "+o.CSS_CLASSES.hidden+'">{resetStr}</div>'+"</div>"+"",o.HANDLE_TEMPLATE='<div class="'+o.CSS_CLASSES.handleVml+'" aria-labelledby="" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0" title="{tooltipHandle}">'+'<v:oval stroked="false">'+'<v:fill opacity="20%" color="#6C3A3A"/>'+"</v:oval>"+"</div>"+""),e.extend(o,i,{renderUI:function(){this._renderLabel(),this._renderRing(),this._renderMarker(),this._renderCenterButton(),this._renderHandle(),this.contentBox=this.get("contentBox"),this._originalValue=this.get("value"),this._minValue=this.get("min"),this._maxValue=this.get("max"),this._stepsPerRevolution=this.get("stepsPerRevolution"),this._minTimesWrapped=Math.floor(this._minValue/this._stepsPerRevolution-1),this._maxTimesWrapped=Math.floor(this._maxValue/this._stepsPerRevolution+1),this._timesWrapped=0,this._angle=this._getAngleFromValue(this.get("value")),this._prevAng=this._angle,this._setTimesWrappedFromValue(this._originalValue),this._handleNode.set("aria-valuemin",this._minValue),this._handleNode.set("aria-valuemax",this._maxValue)},_setBorderRadius:function(){this._ringNode.setStyles({WebkitBorderRadius:this._ringNodeRadius+"px",MozBorderRadius:this._ringNodeRadius+"px",borderRadius:this._ringNodeRadius+"px"}),this._handleNode.setStyles({WebkitBorderRadius:this._handleNodeRadius+"px",MozBorderRadius:this._handleNodeRadius+"px",borderRadius:this._handleNodeRadius+"px"}),this._markerNode.setStyles({WebkitBorderRadius:this._markerNodeRadius+"px",MozBorderRadius:this._markerNodeRadius+"px",borderRadius:this._markerNodeRadius+"px"}),this._centerButtonNode.setStyles({WebkitBorderRadius:this._centerButtonNodeRadius+"px",MozBorderRadius:this._centerButtonNodeRadius+"px",borderRadius:this._centerButtonNodeRadius+"px"})},_handleCenterButtonEnter:function(){this._resetString.removeClass(o.CSS_CLASSES.hidden)},_handleCenterButtonLeave:function(){this._resetString.addClass(o.CSS_CLASSES.hidden)},bindUI:function(){this.after("valueChange",this._afterValueChange);var t=this.get("boundingBox"),n=e.UA.opera?"press:":"down:",r=n+"38,40,33,34,35,36",i=n+"37,39",s=n+"37+meta,39+meta",o=e.DD.Drag;e.on("key",e.bind(this._onDirectionKey,this),t,r),e.on("key",e.bind(this._onLeftRightKey,this),t,i),t.on("key",this._onLeftRightKeyMeta,s,this),e.on("mouseenter",e.bind(this._handleCenterButtonEnter,this),this._centerButtonNode),e.on("mouseleave",e.bind(this._handleCenterButtonLeave,this),this._centerButtonNode),e.on("gesturemovestart",e.bind(this._resetDial,this),this._centerButtonNode),e.on("gesturemoveend",e.bind(this._handleCenterButtonMouseup,this),this._centerButtonNode),e.on(o.START_EVENT,e.bind(this._handleHandleMousedown,this),this._handleNode),e.on(o.START_EVENT,e.bind(this._handleMousedown,this),this._ringNode),e.on("gesturemoveend",e.bind(this._handleRingMouseup,this),this._ringNode),this._dd1=new o({node:this._handleNode,on:{"drag:drag":e.bind(this._handleDrag,this),"drag:start":e.bind(this._handleDragStart,this),"drag:end":e.bind(this._handleDragEnd,this)}}),e.bind(this._dd1.addHandle(this._ringNode),this)},_setTimesWrappedFromValue:function(e){e%this._stepsPerRevolution===0?this._timesWrapped=e/this._stepsPerRevolution:this._timesWrapped=Math.floor(e/this._stepsPerRevolution)},_getAngleFromHandleCenter:function(e,t){var n=Math.atan((this._dialCenterY-t)/(this._dialCenterX-e))*(180/Math.PI);return n=this._dialCenterX-e<0?n+90:n+90+180,n},_calculateDialCenter:function(){this._dialCenterX=this._ringNode.get("offsetWidth")/2,this._dialCenterY=this._ringNode.get("offsetHeight")/2},_handleRingMouseup:function(){this._handleNode.focus()},_handleCenterButtonMouseup:function(){this._handleNode.focus()},_handleHandleMousedown:function(){this._handleNode.focus()},_handleDrag:function(e){var t,n,r,i;t=parseInt(this._handleNode.getStyle("left"),10)+this._handleNodeRadius,n=parseInt(this._handleNode.getStyle("top"),10)+this._handleNodeRadius,r=this._getAngleFromHandleCenter(t,n),this._prevAng>270&&r<90?this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._timesWrapped+1):this._prevAng<90&&r>270&&this._timesWrapped>this._minTimesWrapped&&(this._timesWrapped=this._timesWrapped-1),i=this._getValueFromAngle(r),i>this._maxValue+this._stepsPerRevolution?this._timesWrapped--:i<this._minValue-this._stepsPerRevolution&&this._timesWrapped++,this._prevAng=r,this._handleValuesBeyondMinMax(e,i)},_handleMousedown:function(t){if(this._ringNode.compareTo(t.target)){var n=this._getAngleFromValue(this._minValue),r=this._getAngleFromValue(this._maxValue),i,s,o,u,a;e.UA.ios?(o=t.clientX-this._ringNode.getX(),u=t.clientY-this._ringNode.getY()):(o=t.clientX+e.one("document").get("scrollLeft")-this._ringNode.getX(),u=t.clientY+e.one("document").get("scrollTop")-this._ringNode.getY()),a=this._getAngleFromHandleCenter(o,u);if(this._maxValue-this._minValue>this._stepsPerRevolution)Math.abs(this._prevAng-a)>180?this._timesWrapped>this._minTimesWrapped&&this._timesWrapped<this._maxTimesWrapped&&(this._timesWrapped=this._prevAng-a>0?this._timesWrapped+1:this._timesWrapped-1):this._timesWrapped===this._minTimesWrapped&&a-this._prevAng<180&&this._timesWrapped++;else if(this._maxValue-this._minValue===this._stepsPerRevolution)a<n?this._timesWrapped=1:this._timesWrapped=0;else if(n>r)this._prevAng>=n&&a<=(n+r)/2?this._timesWrapped++:this._prevAng<=r&&a>(n+r)/2&&this._timesWrapped--;else if(a<n||a>r){s=((n+r)/2+180)%360,s>180?i=r<a&&a<s?this.get("max"):this.get("min"):i=n>a&&a>s?this.get("min"):this.get("max"),this._prevAng=this._getAngleFromValue(i),this.set("value",i),this._setTimesWrappedFromValue(i);return}i=this._getValueFromAngle(a),this._prevAng=a,this._handleValuesBeyondMinMax(t,i)}},_handleValuesBeyondMinMax:function(e,t){t>=this._minValue&&t<=this._maxValue?(this.set("value",t),e.currentTarget===this._ringNode&&this._dd1._handleMouseDownEvent(e)):t>this._maxValue?(this.set("value",this._maxValue),this._prevAng=this._getAngleFromValue(this._maxValue)):t<this._minValue&&(this.set("value",this._minValue),this._prevAng=this._getAngleFromValue(this._minValue))},_handleDragStart:function(e){this._markerNode.removeClass(o.CSS_CLASSES.hidden)},_handleDragEnd:function(){var t=this._handleNode;t.transition({duration:.08,easing:"ease-in",left:this._setNodeToFixedRadius(this._handleNode,!0)[0]+"px",top:this._setNodeToFixedRadius(this._handleNode,!0)[1]+"px"},e.bind(function(){var e=this.get("value");e>this._minValue&&e<this._maxValue?this._markerNode.addClass(o.CSS_CLASSES.hidden):(this._setTimesWrappedFromValue(e),this._prevAng=this._getAngleFromValue(e))},this))},_setNodeToFixedRadius:function(e,t){var n=this._angle-90,r=Math.PI/180,i=Math.round(Math.sin(n*r)*this._handleDistance),s=Math.round(Math.cos(n*r)*this._handleDistance),o=e.get("offsetWidth");i-=o*.5,s-=o*.5;if(t)return[this._ringNodeRadius+s,this._ringNodeRadius+i];e.setStyle("left",this._ringNodeRadius+s+"px"),e.setStyle("top",this._ringNodeRadius+i+"px")},syncUI:function(){this._setSizes(),this._calculateDialCenter(),this._setBorderRadius(),this._uiSetValue(this.get("value")),this._markerNode.addClass(o.CSS_CLASSES.hidden),this._resetString.addClass(o.CSS_CLASSES.hidden)},_setSizes:function(){var e=this.get("diameter"),t,n,r,i=function(e,t,n){var r="px";e.getElementsByTagName("oval").setStyle("width",t*n+r),e.getElementsByTagName("oval").setStyle("height",t*n+r),e.setStyle("width",t*n+r),e.setStyle("height",t*n+r)};i(this._ringNode,e,1),i(this._handleNode,e,this.get("handleDiameter")),i(this._markerNode,e,this.get("markerDiameter")),i(this._centerButtonNode,e,this.get("centerButtonDiameter")),this._ringNodeRadius=this._ringNode.get("offsetWidth")*.5,this._handleNodeRadius=this._handleNode.get("offsetWidth")*.5,this._markerNodeRadius=this._markerNode.get("offsetWidth")*.5,this._centerButtonNodeRadius=this._centerButtonNode.get("offsetWidth")*.5,this._handleDistance=this._ringNodeRadius*this.get("handleDistance"),t=this._ringNodeRadius-this._centerButtonNodeRadius,this._centerButtonNode.setStyle("left",t+"px"),this._centerButtonNode.setStyle("top",t+"px"),n=this._centerButtonNodeRadius-this._resetString.get("offsetWidth")*.5,r=this._centerButtonNodeRadius-this._resetString.get("offsetHeight")*.5,this._resetString.setStyles({left:n+"px",top:r+"px"})},_renderLabel:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.label);n||(n=s.create(e.Lang.sub(o.LABEL_TEMPLATE,this.get("strings"))),t.append(n)),this._labelNode=n,this._valueStringNode=this._labelNode.one("."+o.CSS_CLASSES.valueString)},_renderRing:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.ring);t||(t=e.appendChild(o.RING_TEMPLATE),t.setStyles({width:this.get("diameter")+"px",height:this.get("diameter")+"px"})),this._ringNode=t},_renderMarker:function(){var e=this.get("contentBox"),t=e.one("."+o.CSS_CLASSES.marker);t||(t=e.one("."+o.CSS_CLASSES.ring).appendChild(o.MARKER_TEMPLATE)),this._markerNode=t},_renderCenterButton:function(){var t=this.get("contentBox"),n=t.one("."+o.CSS_CLASSES.centerButton);n||(n=s.create(e.Lang.sub(o.CENTER_BUTTON_TEMPLATE,this.get("strings"))),t.one("."+o.CSS_CLASSES.ring).append(n)),this._centerButtonNode=n,this._resetString=this._centerButtonNode.one("."+o.CSS_CLASSES.resetString)},_renderHandle:function(){var t=o.CSS_CLASSES.label+e.guid(),n=this.get("contentBox"),r=n.one("."+o.CSS_CLASSES.handle);r||(r=s.create(e.Lang.sub(o.HANDLE_TEMPLATE,this.get("strings"))),r.setAttribute("aria-labelledby",t),this._labelNode.one("."+o.CSS_CLASSES.labelString).setAttribute("id",t),n.one("."+o.CSS_CLASSES.ring).append(r)),this._handleNode=r},_setLabelString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.labelString).setHTML(e)},_setResetString:function(e){this.get("contentBox").one("."+o.CSS_CLASSES.resetString).setHTML(e)},_setTooltipString:function(e){this._handleNode.set("title",e)},_onDirectionKey:function(e){e.preventDefault();switch(e.charCode){case 38:this._incrMinor();break;case 40:this._decrMinor();break;case 36:this._setToMin();break;case 35:this._setToMax();break;case 33:this._incrMajor();break;case 34:this._decrMajor()}},_onLeftRightKey:function(e){e.preventDefault();switch(e.charCode){case 37:this._decrMinor();break;case 39:this._incrMinor()}},_onLeftRightKeyMeta:function(e){e.preventDefault();switch(e.charCode){case 37:this._setToMin();break;case 39:this._setToMax()}},_incrMinor:function(){var e=this.get("value")+this.get("minorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMinor:function(){var e=this.get("value")-this.get("minorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_incrMajor:function(){var e=this.get("value")+this.get("majorStep");e=Math.min(e,this.get("max")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_decrMajor:function(){var e=this.get("value")-this.get("majorStep");e=Math.max(e,this.get("min")),this.set("value",e.toFixed(this.get("decimalPlaces"))-0)},_setToMax:function(){this.set("value",this.get("max"))},_setToMin:function(){this.set("value",this.get("min"))},_resetDial:function(e){e&&e.stopPropagation(),this.set("value",this._originalValue),this._resetString.addClass(o.CSS_CLASSES.hidden),this._handleNode.focus()},_getAngleFromValue:function(e){var t=e%this._stepsPerRevolution,n=t/this._stepsPerRevolution*360;return n<0?n+360:n},_getValueFromAngle:function(e){e<0?e=360+e:e===0&&(e=360);var t=e/360*this._stepsPerRevolution;return t+=this._timesWrapped*this._stepsPerRevolution,t.toFixed(this.get("decimalPlaces"))-0},_afterValueChange:function(e){this._uiSetValue(e.newVal)},_valueToDecimalPlaces:function(e){},_uiSetValue:function(e){this._angle=this._getAngleFromValue(e),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&(this._setTimesWrappedFromValue(e),this._setNodeToFixedRadius(this._handleNode,!1),this._prevAng=this._getAngleFromValue(this.get("value"))),this._valueStringNode.setHTML(e.toFixed(this.get("decimalPlaces"))),this._handleNode.set("aria-valuenow",e),this._handleNode.set("aria-valuetext",e),this._setNodeToFixedRadius(this._markerNode,!1),e===this._maxValue||e===this._minValue?(this._markerNode.addClass(o.CSS_CLASSES.markerMaxMin),n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#AB3232"),this._markerNode.removeClass(o.CSS_CLASSES.hidden)):(n===!0&&this._markerNode.getElementsByTagName("fill").set("color","#000"),this._markerNode.removeClass(o.CSS_CLASSES.markerMaxMin),this._handleNode.hasClass(o.CSS_CLASSES.dragging)===!1&&this._markerNode.addClass(o.CSS_CLASSES.hidden))},_validateValue:function(e){var t=this.get("min"),n=this.get("max");return r.isNumber(e)&&e>=t&&e<=n}}),e.Dial=o},"3.7.3",{requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],lang:["en","es"],skinnable:!0});
diff --git a/js/yui3/dial/lang/dial.js b/js/yui3/dial/lang/dial.js
new file mode 100644
index 000000000..5a09d3827
--- /dev/null
+++ b/js/yui3/dial/lang/dial.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/dial",function(e){e.Intl.add("dial","",{label:"My label",resetStr:"Reset",tooltipHandle:"Drag to set value"})},"3.7.3");
diff --git a/js/yui3/dial/lang/dial_en.js b/js/yui3/dial/lang/dial_en.js
new file mode 100644
index 000000000..15b684655
--- /dev/null
+++ b/js/yui3/dial/lang/dial_en.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/dial_en",function(e){e.Intl.add("dial","en",{label:"My label",resetStr:"Reset",tooltipHandle:"Drag to set value"})},"3.7.3");
diff --git a/js/yui3/dial/lang/dial_es.js b/js/yui3/dial/lang/dial_es.js
new file mode 100644
index 000000000..4376c579b
--- /dev/null
+++ b/js/yui3/dial/lang/dial_es.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lang/dial_es",function(e){e.Intl.add("dial","es",{label:"Mi etiqueta",resetStr:"Resetear",tooltipHandle:"Arrastre para ajustar el valor"})},"3.7.3");
diff --git a/js/yui3/dom-attrs/dom-attrs-min.js b/js/yui3/dom-attrs/dom-attrs-min.js
new file mode 100644
index 000000000..89089428d
--- /dev/null
+++ b/js/yui3/dom-attrs/dom-attrs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-attrs",function(h){var e=h.config.doc.documentElement,b=h.DOM,a="tagName",g="ownerDocument",c="",f=h.Features.add,d=h.Features.test;h.mix(b,{getText:(e.textContent!==undefined)?function(j){var i="";if(j){i=j.textContent;}return i||"";}:function(j){var i="";if(j){i=j.innerText||j.nodeValue;}return i||"";},setText:(e.textContent!==undefined)?function(i,j){if(i){i.textContent=j;}}:function(i,j){if("innerText" in i){i.innerText=j;}else{if("nodeValue" in i){i.nodeValue=j;}}},CUSTOM_ATTRIBUTES:(!e.hasAttribute)?{"for":"htmlFor","class":"className"}:{"htmlFor":"for","className":"class"},setAttribute:function(k,i,l,j){if(k&&i&&k.setAttribute){i=b.CUSTOM_ATTRIBUTES[i]||i;k.setAttribute(i,l,j);}},getAttribute:function(l,i,k){k=(k!==undefined)?k:2;var j="";if(l&&i&&l.getAttribute){i=b.CUSTOM_ATTRIBUTES[i]||i;j=l.getAttribute(i,k);if(j===null){j="";}}return j;},VALUE_SETTERS:{},VALUE_GETTERS:{},getValue:function(k){var j="",i;if(k&&k[a]){i=b.VALUE_GETTERS[k[a].toLowerCase()];if(i){j=i(k);}else{j=k.value;}}if(j===c){j=c;}return(typeof j==="string")?j:"";},setValue:function(i,j){var k;if(i&&i[a]){k=b.VALUE_SETTERS[i[a].toLowerCase()];if(k){k(i,j);}else{i.value=j;}}},creators:{}});f("value-set","select",{test:function(){var i=h.config.doc.createElement("select");i.innerHTML="<option>1</option><option>2</option>";i.value="2";return(i.value&&i.value==="2");}});if(!d("value-set","select")){b.VALUE_SETTERS.select=function(m,n){for(var k=0,j=m.getElementsByTagName("option"),l;l=j[k++];){if(b.getValue(l)===n){l.selected=true;break;}}};}h.mix(b.VALUE_GETTERS,{button:function(i){return(i.attributes&&i.attributes.value)?i.attributes.value.value:"";}});h.mix(b.VALUE_SETTERS,{button:function(j,k){var i=j.attributes.value;if(!i){i=j[g].createAttribute("value");j.setAttributeNode(i);}i.value=k;}});h.mix(b.VALUE_GETTERS,{option:function(j){var i=j.attributes;return(i.value&&i.value.specified)?j.value:j.text;},select:function(j){var k=j.value,i=j.options;if(i&&i.length){if(j.multiple){}else{k=b.getValue(i[j.selectedIndex]);}}return k;}});},"3.7.3",{requires:["dom-core"]}); \ No newline at end of file
diff --git a/js/yui3/dom-base/dom-base-min.js b/js/yui3/dom-base/dom-base-min.js
new file mode 100644
index 000000000..dbf77163d
--- /dev/null
+++ b/js/yui3/dom-base/dom-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-base",function(e,t){var n=e.config.doc.documentElement,r=e.DOM,i="tagName",s="ownerDocument",o="",u=e.Features.add,a=e.Features.test;e.mix(r,{getText:n.textContent!==undefined?function(e){var t="";return e&&(t=e.textContent),t||""}:function(e){var t="";return e&&(t=e.innerText||e.nodeValue),t||""},setText:n.textContent!==undefined?function(e,t){e&&(e.textContent=t)}:function(e,t){"innerText"in e?e.innerText=t:"nodeValue"in e&&(e.nodeValue=t)},CUSTOM_ATTRIBUTES:n.hasAttribute?{htmlFor:"for",className:"class"}:{"for":"htmlFor","class":"className"},setAttribute:function(e,t,n,i){e&&t&&e.setAttribute&&(t=r.CUSTOM_ATTRIBUTES[t]||t,e.setAttribute(t,n,i))},getAttribute:function(e,t,n){n=n!==undefined?n:2;var i="";return e&&t&&e.getAttribute&&(t=r.CUSTOM_ATTRIBUTES[t]||t,i=e.getAttribute(t,n),i===null&&(i="")),i},VALUE_SETTERS:{},VALUE_GETTERS:{},getValue:function(e){var t="",n;return e&&e[i]&&(n=r.VALUE_GETTERS[e[i].toLowerCase()],n?t=n(e):t=e.value),t===o&&(t=o),typeof t=="string"?t:""},setValue:function(e,t){var n;e&&e[i]&&(n=r.VALUE_SETTERS[e[i].toLowerCase()],n?n(e,t):e.value=t)},creators:{}}),u("value-set","select",{test:function(){var t=e.config.doc.createElement("select");return t.innerHTML="<option>1</option><option>2</option>",t.value="2",t.value&&t.value==="2"}}),a("value-set","select")||(r.VALUE_SETTERS.select=function(e,t){for(var n=0,i=e.getElementsByTagName("option"),s;s=i[n++];)if(r.getValue(s)===t){s.selected=!0;break}}),e.mix(r.VALUE_GETTERS,{button:function(e){return e.attributes&&e.attributes.value?e.attributes.value.value:""}}),e.mix(r.VALUE_SETTERS,{button:function(e,t){var n=e.attributes.value;n||(n=e[s].createAttribute("value"),e.setAttributeNode(n)),n.value=t}}),e.mix(r.VALUE_GETTERS,{option:function(e){var t=e.attributes;return t.value&&t.value.specified?e.value:e.text},select:function(e){var t=e.value,n=e.options;return n&&n.length&&(e.multiple||e.selectedIndex>-1&&(t=r.getValue(n[e.selectedIndex]))),t}});var f,l,c;e.mix(e.DOM,{hasClass:function(t,n){var r=e.DOM._getRegExp("(?:^|\\s+)"+n+"(?:\\s+|$)");return r.test(t.className)},addClass:function(t,n){e.DOM.hasClass(t,n)||(t.className=e.Lang.trim([t.className,n].join(" ")))},removeClass:function(t,n){n&&l(t,n)&&(t.className=e.Lang.trim(t.className.replace(e.DOM._getRegExp("(?:^|\\s+)"+n+"(?:\\s+|$)")," ")),l(t,n)&&c(t,n))},replaceClass:function(e,t,n){c(e,t),f(e,n)},toggleClass:function(e,t,n){var r=n!==undefined?n:!l(e,t);r?f(e,t):c(e,t)}}),l=e.DOM.hasClass,c=e.DOM.removeClass,f=e.DOM.addClass;var h=/<([a-z]+)/i,r=e.DOM,u=e.Features.add,a=e.Features.test,p={},d=function(t,n){var r=e.config.doc.createElement("div"),i=!0;r.innerHTML=t;if(!r.firstChild||r.firstChild.tagName!==n.toUpperCase())i=!1;return i},v=/(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,m="<table>",g="</table>";e.mix(e.DOM,{_fragClones:{},_create:function(e,t,n){n=n||"div";var i=r._fragClones[n];return i?i=i.cloneNode(!1):i=r._fragClones[n]=t.createElement(n),i.innerHTML=e,i},_children:function(e,t){var n=0,r=e.children,i,s,o;r&&r.tags&&(t?r=e.children.tags(t):s=r.tags("!").length);if(!r||!r.tags&&t||s){i=r||e.childNodes,r=[];while(o=i[n++])o.nodeType===1&&(!t||t===o.tagName)&&r.push(o)}return r||[]},create:function(t,n){typeof t=="string"&&(t=e.Lang.trim(t)),n=n||e.config.doc;var i=h.exec(t),s=r._create,o=p,u=null,a,f,l;return t!=undefined&&(i&&i[1]&&(a=o[i[1].toLowerCase()],typeof a=="function"?s=a:f=a),l=s(t,n,f).childNodes,l.length===1?u=l[0].parentNode.removeChild(l[0]):l[0]&&l[0].className==="yui3-big-dummy"?l.length===2?u=l[0].nextSibling:(l[0].parentNode.removeChild(l[0]),u=r._nl2frag(l,n)):u=r._nl2frag(l,n)),u},_nl2frag:function(t,n){var r=null,i,s;if(t&&(t.push||t.item)&&t[0]){n=n||t[0].ownerDocument,r=n.createDocumentFragment(),t.item&&(t=e.Array(t,0,!0));for(i=0,s=t.length;i<s;i++)r.appendChild(t[i])}return r},addHTML:function(t,n,i){var s=t.parentNode,o=0,u,a=n,f;if(n!=undefined)if(n.nodeType)f=n;else if(typeof n=="string"||typeof n=="number")a=f=r.create(n);else if(n[0]&&n[0].nodeType){f=e.config.doc.createDocumentFragment();while(u=n[o++])f.appendChild(u)}if(i)if(f&&i.parentNode)i.parentNode.insertBefore(f,i);else switch(i){case"replace":while(t.firstChild)t.removeChild(t.firstChild);f&&t.appendChild(f);break;case"before":f&&s.insertBefore(f,t);break;case"after":f&&(t.nextSibling?s.insertBefore(f,t.nextSibling):s.appendChild(f));break;default:f&&t.appendChild(f)}else f&&t.appendChild(f);return a},wrap:function(t,n){var r=n&&n.nodeType?n:e.DOM.create(n),i=r.getElementsByTagName("*");i.length&&(r=i[i.length-1]),t.parentNode&&t.parentNode.replaceChild(r,t),r.appendChild(t)},unwrap:function(e){var t=e.parentNode,n=t.lastChild,r=e,i;if(t){i=t.parentNode;if(i){e=t.firstChild;while(e!==n)r=e.nextSibling,i.insertBefore(e,t),e=r;i.replaceChild(n,t)}else t.removeChild(e)}}}),u("innerhtml","table",{test:function(){var t=e.config.doc.createElement("table");try{t.innerHTML="<tbody></tbody>"}catch(n){return!1}return t.firstChild&&t.firstChild.nodeName==="TBODY"}}),u("innerhtml-div","tr",{test:function(){return d("<tr></tr>","tr")}}),u("innerhtml-div","script",{test:function(){return d("<script></script>","script")}}),a("innerhtml","table")||(p.tbody=function(t,n){var i=r.create(m+t+g,n),s=e.DOM._children(i,"tbody")[0];return i.children.length>1&&s&&!v.test(t)&&s.parentNode.removeChild(s),i}),a("innerhtml-div","script")||(p.script=function(e,t){var n=t.createElement("div");return n.innerHTML="-"+e,n.removeChild(n.firstChild),n},p.link=p.style=p.script),a("innerhtml-div","tr")||(e.mix(p,{option:function(e,t){return r.create('<select><option class="yui3-big-dummy" selected></option>'+e+"</select>",t)},tr:function(e,t){return r.create("<tbody>"+e+"</tbody>",t)},td:function(e,t){return r.create("<tr>"+e+"</tr>",t)},col:function(e,t){return r.create("<colgroup>"+e+"</colgroup>",t)},tbody:"table"}),e.mix(p,{legend:"fieldset",th:p.td,thead:p.tbody,tfoot:p.tbody,caption:p.tbody,colgroup:p.tbody,optgroup:p.option})),r.creators=p,e.mix(e.DOM,{setWidth:function(t,n){e.DOM._setSize(t,"width",n)},setHeight:function(t,n){e.DOM._setSize(t,"height",n)},_setSize:function(e,t,n){n=n>0?n:0;var r=0;e.style[t]=n+"px",r=t==="height"?e.offsetHeight:e.offsetWidth,r>n&&(n-=r-n,n<0&&(n=0),e.style[t]=n+"px")}})},"3.7.3",{requires:["dom-core"]});
diff --git a/js/yui3/dom-class/dom-class-min.js b/js/yui3/dom-class/dom-class-min.js
new file mode 100644
index 000000000..d3376721c
--- /dev/null
+++ b/js/yui3/dom-class/dom-class-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-class",function(d){var b,a,c;d.mix(d.DOM,{hasClass:function(g,f){var e=d.DOM._getRegExp("(?:^|\\s+)"+f+"(?:\\s+|$)");return e.test(g.className);},addClass:function(f,e){if(!d.DOM.hasClass(f,e)){f.className=d.Lang.trim([f.className,e].join(" "));}},removeClass:function(f,e){if(e&&a(f,e)){f.className=d.Lang.trim(f.className.replace(d.DOM._getRegExp("(?:^|\\s+)"+e+"(?:\\s+|$)")," "));if(a(f,e)){c(f,e);}}},replaceClass:function(f,e,g){c(f,e);b(f,g);},toggleClass:function(f,e,g){var h=(g!==undefined)?g:!(a(f,e));if(h){b(f,e);}else{c(f,e);}}});a=d.DOM.hasClass;c=d.DOM.removeClass;b=d.DOM.addClass;},"3.7.3",{requires:["dom-core"]}); \ No newline at end of file
diff --git a/js/yui3/dom-core/dom-core-min.js b/js/yui3/dom-core/dom-core-min.js
new file mode 100644
index 000000000..77c97480d
--- /dev/null
+++ b/js/yui3/dom-core/dom-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-core",function(e,t){var n="nodeType",r="ownerDocument",i="documentElement",s="defaultView",o="parentWindow",u="tagName",a="parentNode",f="previousSibling",l="nextSibling",c="contains",h="compareDocumentPosition",p=[],d=function(){var t=e.config.doc.createElement("div"),n=t.appendChild(e.config.doc.createTextNode("")),r=!1;try{r=t.contains(n)}catch(i){}return r}(),v={byId:function(e,t){return v.allById(e,t)[0]||null},getId:function(e){var t;return e.id&&!e.id.tagName&&!e.id.item?t=e.id:e.attributes&&e.attributes.id&&(t=e.attributes.id.value),t},setId:function(e,t){e.setAttribute?e.setAttribute("id",t):e.id=t},ancestor:function(e,t,n,r){var i=null;return n&&(i=!t||t(e)?e:null),i||v.elementByAxis(e,a,t,null,r)},ancestors:function(e,t,n,r){var i=e,s=[];while(i=v.ancestor(i,t,n,r)){n=!1;if(i){s.unshift(i);if(r&&r(i))return s}}return s},elementByAxis:function(e,t,n,r,i){while(e&&(e=e[t])){if((r||e[u])&&(!n||n(e)))return e;if(i&&i(e))return null}return null},contains:function(e,t){var r=!1;if(!t||!e||!t[n]||!e[n])r=!1;else if(e[c]&&(t[n]===1||d))r=e[c](t);else if(e[h]){if(e===t||!!(e[h](t)&16))r=!0}else r=v._bruteContains(e,t);return r},inDoc:function(e,t){var n=!1,s;return e&&e.nodeType&&(t||(t=e[r]),s=t[i],s&&s.contains&&e.tagName?n=s.contains(e):n=v.contains(s,e)),n},allById:function(t,n){n=n||e.config.doc;var r=[],i=[],s,o;if(n.querySelectorAll)i=n.querySelectorAll('[id="'+t+'"]');else if(n.all){r=n.all(t);if(r){r.nodeName&&(r.id===t?(i.push(r),r=p):r=[r]);if(r.length)for(s=0;o=r[s++];)(o.id===t||o.attributes&&o.attributes.id&&o.attributes.id.value===t)&&i.push(o)}}else i=[v._getDoc(n).getElementById(t)];return i},isWindow:function(e){return!!(e&&e.scrollTo&&e.document)},_removeChildNodes:function(e){while(e.firstChild)e.removeChild(e.firstChild)},siblings:function(e,t){var n=[],r=e;while(r=r[f])r[u]&&(!t||t(r))&&n.unshift(r);r=e;while(r=r[l])r[u]&&(!t||t(r))&&n.push(r);return n},_bruteContains:function(e,t){while(t){if(e===t)return!0;t=t.parentNode}return!1},_getRegExp:function(e,t){return t=t||"",v._regexCache=v._regexCache||{},v._regexCache[e+t]||(v._regexCache[e+t]=new RegExp(e,t)),v._regexCache[e+t]},_getDoc:function(t){var i=e.config.doc;return t&&(i=t[n]===9?t:t[r]||t.document||e.config.doc),i},_getWin:function(t){var n=v._getDoc(t);return n[s]||n[o]||e.config.win},_batch:function(e,t,n,r,i,s){t=typeof t=="string"?v[t]:t;var o,u=0,a,f;if(t&&e)while(a=e[u++])o=o=t.call(v,a,n,r,i,s),typeof o!="undefined"&&(f||(f=[]),f.push(o));return typeof f!="undefined"?f:e},generateID:function(t){var n=t.id;return n||(n=e.stamp(t),t.id=n),n}};e.DOM=v},"3.7.3",{requires:["oop","features"]});
diff --git a/js/yui3/dom-create/dom-create-min.js b/js/yui3/dom-create/dom-create-min.js
new file mode 100644
index 000000000..a6c8b7bc1
--- /dev/null
+++ b/js/yui3/dom-create/dom-create-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-create",function(a){var c=/<([a-z]+)/i,d=a.DOM,i=a.Features.add,g=a.Features.test,f={},e=function(m,k){var n=a.config.doc.createElement("div"),l=true;n.innerHTML=m;if(!n.firstChild||n.firstChild.tagName!==k.toUpperCase()){l=false;}return l;},j=/(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,b="<table>",h="</table>";a.mix(a.DOM,{_fragClones:{},_create:function(l,m,k){k=k||"div";var n=d._fragClones[k];if(n){n=n.cloneNode(false);}else{n=d._fragClones[k]=m.createElement(k);}n.innerHTML=l;return n;},create:function(p,s){if(typeof p==="string"){p=a.Lang.trim(p);}s=s||a.config.doc;var o=c.exec(p),q=d._create,l=f,r=null,n,t,k;if(p!=undefined){if(o&&o[1]){n=l[o[1].toLowerCase()];if(typeof n==="function"){q=n;}else{t=n;}}k=q(p,s,t).childNodes;if(k.length===1){r=k[0].parentNode.removeChild(k[0]);}else{if(k[0]&&k[0].className==="yui3-big-dummy"){if(k.length===2){r=k[0].nextSibling;}else{k[0].parentNode.removeChild(k[0]);r=d._nl2frag(k,s);}}else{r=d._nl2frag(k,s);}}}return r;},_nl2frag:function(l,o){var m=null,n,k;if(l&&(l.push||l.item)&&l[0]){o=o||l[0].ownerDocument;m=o.createDocumentFragment();if(l.item){l=a.Array(l,0,true);}for(n=0,k=l.length;n<k;n++){m.appendChild(l[n]);}}return m;},addHTML:function(r,q,m){var k=r.parentNode,o=0,p,l=q,n;if(q!=undefined){if(q.nodeType){n=q;}else{if(typeof q=="string"||typeof q=="number"){l=n=d.create(q);}else{if(q[0]&&q[0].nodeType){n=a.config.doc.createDocumentFragment();while((p=q[o++])){n.appendChild(p);}}}}}if(m){if(m.nodeType){m.parentNode.insertBefore(n,m);}else{switch(m){case"replace":while(r.firstChild){r.removeChild(r.firstChild);}if(n){r.appendChild(n);}break;case"before":k.insertBefore(n,r);break;case"after":if(r.nextSibling){k.insertBefore(n,r.nextSibling);}else{k.appendChild(n);}break;default:r.appendChild(n);}}}else{if(n){r.appendChild(n);}}return l;}});i("innerhtml","table",{test:function(){var k=a.config.doc.createElement("table");try{k.innerHTML="<tbody></tbody>";}catch(l){return false;}return(k.firstChild&&k.firstChild.nodeName==="TBODY");}});i("innerhtml-div","tr",{test:function(){return e("<tr></tr>","tr");}});i("innerhtml-div","script",{test:function(){return e("<script><\/script>","script");}});if(!g("innerhtml","table")){f.tbody=function(l,m){var n=d.create(b+l+h,m),k=n.children.tags("tbody")[0];if(n.children.length>1&&k&&!j.test(l)){k.parentNode.removeChild(k);}return n;};}if(!g("innerhtml-div","script")){f.script=function(k,l){var m=l.createElement("div");m.innerHTML="-"+k;m.removeChild(m.firstChild);return m;};f.link=f.style=f.script;}if(!g("innerhtml-div","tr")){a.mix(f,{option:function(k,l){return d.create('<select><option class="yui3-big-dummy" selected></option>'+k+"</select>",l);},tr:function(k,l){return d.create("<tbody>"+k+"</tbody>",l);},td:function(k,l){return d.create("<tr>"+k+"</tr>",l);},col:function(k,l){return d.create("<colgroup>"+k+"</colgroup>",l);},tbody:"table"});a.mix(f,{legend:"fieldset",th:f.td,thead:f.tbody,tfoot:f.tbody,caption:f.tbody,colgroup:f.tbody,optgroup:f.option});}d.creators=f;},"3.7.3",{requires:["dom-core"]}); \ No newline at end of file
diff --git a/js/yui3/dom-deprecated/dom-deprecated-min.js b/js/yui3/dom-deprecated/dom-deprecated-min.js
new file mode 100644
index 000000000..c77e31f3a
--- /dev/null
+++ b/js/yui3/dom-deprecated/dom-deprecated-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-deprecated",function(e,t){e.mix(e.DOM,{children:function(t,n){var r=[];return t&&(n=n||"*",r=e.Selector.query("> "+n,t)),r},firstByTag:function(t,n){var r;return n=n||e.config.doc,t&&n.getElementsByTagName&&(r=n.getElementsByTagName(t)[0]),r||null},previous:function(t,n,r){return e.DOM.elementByAxis(t,"previousSibling",n,r)},next:function(t,n,r){return e.DOM.elementByAxis(t,"nextSibling",n,r)}})},"3.7.3",{requires:["dom-base"]});
diff --git a/js/yui3/dom-screen/dom-screen-min.js b/js/yui3/dom-screen/dom-screen-min.js
new file mode 100644
index 000000000..3ed17b56a
--- /dev/null
+++ b/js/yui3/dom-screen/dom-screen-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-screen",function(e,t){(function(e){var t="documentElement",n="compatMode",r="position",i="fixed",s="relative",o="left",u="top",a="BackCompat",f="medium",l="borderLeftWidth",c="borderTopWidth",h="getBoundingClientRect",p="getComputedStyle",d=e.DOM,v=/^t(?:able|d|h)$/i,m;e.UA.ie&&(e.config.doc[n]!=="BackCompat"?m=t:m="body"),e.mix(d,{winHeight:function(e){var t=d._getWinSize(e).height;return t},winWidth:function(e){var t=d._getWinSize(e).width;return t},docHeight:function(e){var t=d._getDocSize(e).height;return Math.max(t,d._getWinSize(e).height)},docWidth:function(e){var t=d._getDocSize(e).width;return Math.max(t,d._getWinSize(e).width)},docScrollX:function(n,r){r=r||n?d._getDoc(n):e.config.doc;var i=r.defaultView,s=i?i.pageXOffset:0;return Math.max(r[t].scrollLeft,r.body.scrollLeft,s)},docScrollY:function(n,r){r=r||n?d._getDoc(n):e.config.doc;var i=r.defaultView,s=i?i.pageYOffset:0;return Math.max(r[t].scrollTop,r.body.scrollTop,s)},getXY:function(){return e.config.doc[t][h]?function(r){var i=null,s,o,u,f,l,c,p,v,g,y;if(r&&r.tagName){p=r.ownerDocument,u=p[n],u!==a?y=p[t]:y=p.body,y.contains?g=y.contains(r):g=e.DOM.contains(y,r);if(g){v=p.defaultView,v&&"pageXOffset"in v?(s=v.pageXOffset,o=v.pageYOffset):(s=m?p[m].scrollLeft:d.docScrollX(r,p),o=m?p[m].scrollTop:d.docScrollY(r,p)),e.UA.ie&&(!p.documentMode||p.documentMode<8||u===a)&&(l=y.clientLeft,c=y.clientTop),f=r[h](),i=[f.left,f.top];if(l||c)i[0]-=l,i[1]-=c;if(o||s)if(!e.UA.ios||e.UA.ios>=4.2)i[0]+=s,i[1]+=o}else i=d._getOffset(r)}return i}:function(t){var n=null,s,o,u,a,f;if(t)if(d.inDoc(t)){n=[t.offsetLeft,t.offsetTop],s=t.ownerDocument,o=t,u=e.UA.gecko||e.UA.webkit>519?!0:!1;while(o=o.offsetParent)n[0]+=o.offsetLeft,n[1]+=o.offsetTop,u&&(n=d._calcBorders(o,n));if(d.getStyle(t,r)!=i){o=t;while(o=o.parentNode){a=o.scrollTop,f=o.scrollLeft,e.UA.gecko&&d.getStyle(o,"overflow")!=="visible"&&(n=d._calcBorders(o,n));if(a||f)n[0]-=f,n[1]-=a}n[0]+=d.docScrollX(t,s),n[1]+=d.docScrollY(t,s)}else n[0]+=d.docScrollX(t,s),n[1]+=d.docScrollY(t,s)}else n=d._getOffset(t);return n}}(),getScrollbarWidth:e.cached(function(){var t=e.config.doc,n=t.createElement("div"),r=t.getElementsByTagName("body")[0],i=.1;return r&&(n.style.cssText="position:absolute;visibility:hidden;overflow:scroll;width:20px;",n.appendChild(t.createElement("p")).style.height="1px",r.insertBefore(n,r.firstChild),i=n.offsetWidth-n.clientWidth,r.removeChild(n)),i},null,.1),getX:function(e){return d.getXY(e)[0]},getY:function(e){return d.getXY(e)[1]},setXY:function(e,t,n){var i=d.setStyle,a,f,l,c;e&&t&&(a=d.getStyle(e,r),f=d._getOffset(e),a=="static"&&(a=s,i(e,r,a)),c=d.getXY(e),t[0]!==null&&i(e,o,t[0]-c[0]+f[0]+"px"),t[1]!==null&&i(e,u,t[1]-c[1]+f[1]+"px"),n||(l=d.getXY(e),(l[0]!==t[0]||l[1]!==t[1])&&d.setXY(e,t,!0)))},setX:function(e,t){return d.setXY(e,[t,null])},setY:function(e,t){return d.setXY(e,[null,t])},swapXY:function(e,t){var n=d.getXY(e);d.setXY(e,d.getXY(t)),d.setXY(t,n)},_calcBorders:function(t,n){var r=parseInt(d[p](t,c),10)||0,i=parseInt(d[p](t,l),10)||0;return e.UA.gecko&&v.test(t.tagName)&&(r=0,i=0),n[0]+=i,n[1]+=r,n},_getWinSize:function(r,i){i=i||r?d._getDoc(r):e.config.doc;var s=i.defaultView||i.parentWindow,o=i[n],u=s.innerHeight,a=s.innerWidth,f=i[t];return o&&!e.UA.opera&&(o!="CSS1Compat"&&(f=i.body),u=f.clientHeight,a=f.clientWidth),{height:u,width:a}},_getDocSize:function(r){var i=r?d._getDoc(r):e.config.doc,s=i[t];return i[n]!="CSS1Compat"&&(s=i.body),{height:s.scrollHeight,width:s.scrollWidth}}})})(e),function(e){var t="top",n="right",r="bottom",i="left",s=function(e,s){var o=Math.max(e[t],s[t]),u=Math.min(e[n],s[n]),a=Math.min(e[r],s[r]),f=Math.max(e[i],s[i]),l={};return l[t]=o,l[n]=u,l[r]=a,l[i]=f,l},o=e.DOM;e.mix(o,{region:function(e){var t=o.getXY(e),n=!1;return e&&t&&(n=o._getRegion(t[1],t[0]+e.offsetWidth,t[1]+e.offsetHeight,t[0])),n},intersect:function(u,a,f){var l=f||o.region(u),c={},h=a,p;if(h.tagName)c=o.region(h);else{if(!e.Lang.isObject(a))return!1;c=a}return p=s(c,l),{top:p[t],right:p[n],bottom:p[r],left:p[i],area:(p[r]-p[t])*(p[n]-p[i]),yoff:p[r]-p[t],xoff:p[n]-p[i],inRegion:o.inRegion(u,a,!1,f)}},inRegion:function(u,a,f,l){var c={},h=l||o.region(u),p=a,d;if(p.tagName)c=o.region(p);else{if(!e.Lang.isObject(a))return!1;c=a}return f?h[i]>=c[i]&&h[n]<=c[n]&&h[t]>=c[t]&&h[r]<=c[r]:(d=s(c,h),d[r]>=d[t]&&d[n]>=d[i]?!0:!1)},inViewportRegion:function(e,t,n){return o.inRegion(e,o.viewportRegion(e),t,n)},_getRegion:function(e,s,o,u){var a={};return a[t]=a[1]=e,a[i]=a[0]=u,a[r]=o,a[n]=s,a.width=a[n]-a[i],a.height=a[r]-a[t],a},viewportRegion:function(t){t=t||e.config.doc.documentElement;var n=!1,r,i;return t&&(r=o.docScrollX(t),i=o.docScrollY(t),n=o._getRegion(i,o.winWidth(t)+r,i+o.winHeight(t),r)),n}})}(e)},"3.7.3",{requires:["dom-base","dom-style"]});
diff --git a/js/yui3/dom-size/dom-size-min.js b/js/yui3/dom-size/dom-size-min.js
new file mode 100644
index 000000000..36f4008d1
--- /dev/null
+++ b/js/yui3/dom-size/dom-size-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-size",function(a){a.mix(a.DOM,{setWidth:function(c,b){a.DOM._setSize(c,"width",b);},setHeight:function(c,b){a.DOM._setSize(c,"height",b);},_setSize:function(c,e,d){d=(d>0)?d:0;var b=0;c.style[e]=d+"px";b=(e==="height")?c.offsetHeight:c.offsetWidth;if(b>d){d=d-(b-d);if(d<0){d=0;}c.style[e]=d+"px";}}});},"3.7.3",{requires:["dom-core"]}); \ No newline at end of file
diff --git a/js/yui3/dom-style-ie/dom-style-ie-min.js b/js/yui3/dom-style-ie/dom-style-ie-min.js
new file mode 100644
index 000000000..62a404688
--- /dev/null
+++ b/js/yui3/dom-style-ie/dom-style-ie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-style-ie",function(e,t){(function(e){var t="hasLayout",n="px",r="filter",i="filters",s="opacity",o="auto",u="borderWidth",a="borderTopWidth",f="borderRightWidth",l="borderBottomWidth",c="borderLeftWidth",h="width",p="height",d="transparent",v="visible",m="getComputedStyle",g=undefined,y=e.config.doc.documentElement,b=e.Features.test,w=e.Features.add,E=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,S=e.UA.ie>=8,x=function(e){return e.currentStyle||e.style},T={CUSTOM_STYLES:{},get:function(t,r){var i="",o;return t&&(o=x(t)[r],r===s&&e.DOM.CUSTOM_STYLES[s]?i=e.DOM.CUSTOM_STYLES[s].get(t):!o||o.indexOf&&o.indexOf(n)>-1?i=o:e.DOM.IE.COMPUTED[r]?i=e.DOM.IE.COMPUTED[r](t,r):E.test(o)?i=T.getPixel(t,r)+n:i=o),i},sizeOffsets:{width:["Left","Right"],height:["Top","Bottom"],top:["Top"],bottom:["Bottom"]},getOffset:function(e,t){var r=x(e)[t],i=t.charAt(0).toUpperCase()+t.substr(1),s="offset"+i,u="pixel"+i,a=T.sizeOffsets[t],f=e.ownerDocument.compatMode,l="";return r===o||r.indexOf("%")>-1?(l=e["offset"+i],f!=="BackCompat"&&(a[0]&&(l-=T.getPixel(e,"padding"+a[0]),l-=T.getBorderWidth(e,"border"+a[0]+"Width",1)),a[1]&&(l-=T.getPixel(e,"padding"+a[1]),l-=T.getBorderWidth(e,"border"+a[1]+"Width",1)))):(!e.style[u]&&!e.style[t]&&(e.style[t]=r),l=e.style[u]),l+n},borderMap:{thin:S?"1px":"2px",medium:S?"3px":"4px",thick:S?"5px":"6px"},getBorderWidth:function(e,t,r){var i=r?"":n,s=e.currentStyle[t];return s.indexOf(n)<0&&(T.borderMap[s]&&e.currentStyle.borderStyle!=="none"?s=T.borderMap[s]:s=0),r?parseFloat(s):s},getPixel:function(e,t){var n=null,r=x(e),i=r.right,s=r[t];return e.style.right=s,n=e.style.pixelRight,e.style.right=i,n},getMargin:function(e,t){var r,i=x(e);return i[t]==o?r=0:r=T.getPixel(e,t),r+n},getVisibility:function(e,t){var n;while((n=e.currentStyle)&&n[t]=="inherit")e=e.parentNode;return n?n[t]:v},getColor:function(t,n){var r=x(t)[n];return(!r||r===d)&&e.DOM.elementByAxis(t,"parentNode",null,function(e){r=x(e)[n];if(r&&r!==d)return t=e,!0}),e.Color.toRGB(r)},getBorderColor:function(t,n){var r=x(t),i=r[n]||r.color;return e.Color.toRGB(e.Color.toHex(i))}},N={};w("style","computedStyle",{test:function(){return"getComputedStyle"in e.config.win}}),w("style","opacity",{test:function(){return"opacity"in y.style}}),w("style","filter",{test:function(){return"filters"in y}}),!b("style","opacity")&&b("style","filter")&&(e.DOM.CUSTOM_STYLES[s]={get:function(e){var t=100;try{t=e[i]["DXImageTransform.Microsoft.Alpha"][s]}catch(n){try{t=e[i]("alpha")[s]}catch(r){}}return t/100},set:function(e,n,i){var o,u=x(e),a=u[r];i=i||e.style,n===""&&(o=s in u?u[s]:1,n=o),typeof a=="string"&&(i[r]=a.replace(/alpha([^)]*\))/gi,"")+(n<1?"alpha("+s+"="+n*100+")":""),i[r]||i.removeAttribute(r),u[t]||(i.zoom=1))}});try{e.config.doc.createElement("div").style.height="-1px"}catch(C){e.DOM.CUSTOM_STYLES.height={set:function(e,t,n){var r=parseFloat(t);if(r>=0||t==="auto"||t==="")n.height=t}},e.DOM.CUSTOM_STYLES.width={set:function(e,t,n){var r=parseFloat(t);if(r>=0||t==="auto"||t==="")n.width=t}}}b("style","computedStyle")||(N[h]=N[p]=T.getOffset,N.color=N.backgroundColor=T.getColor,N[u]=N[a]=N[f]=N[l]=N[c]=T.getBorderWidth,N.marginTop=N.marginRight=N.marginBottom=N.marginLeft=T.getMargin,N.visibility=T.getVisibility,N.borderColor=N.borderTopColor=N.borderRightColor=N.borderBottomColor=N.borderLeftColor=T.getBorderColor,e.DOM[m]=T.get,e.namespace("DOM.IE"),e.DOM.IE.COMPUTED=N,e.DOM.IE.ComputedStyle=T)})(e)},"3.7.3",{requires:["dom-style"]});
diff --git a/js/yui3/dom-style/dom-style-min.js b/js/yui3/dom-style/dom-style-min.js
new file mode 100644
index 000000000..2e4e2d6ec
--- /dev/null
+++ b/js/yui3/dom-style/dom-style-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dom-style",function(e,t){(function(e){var t="documentElement",n="defaultView",r="ownerDocument",i="style",s="float",o="cssFloat",u="styleFloat",a="transparent",f="getComputedStyle",l="getBoundingClientRect",c=e.config.win,h=e.config.doc,p=undefined,d=e.DOM,v="transform",m="transformOrigin",g=["WebkitTransform","MozTransform","OTransform","msTransform"],y=/color$/i,b=/width|height|top|left|right|bottom|margin|padding/i;e.Array.each(g,function(e){e in h[t].style&&(v=e,m=e+"Origin")}),e.mix(d,{DEFAULT_UNIT:"px",CUSTOM_STYLES:{},setStyle:function(e,t,n,r){r=r||e.style;var i=d.CUSTOM_STYLES;if(r){n===null||n===""?n="":!isNaN(new Number(n))&&b.test(t)&&(n+=d.DEFAULT_UNIT);if(t in i){if(i[t].set){i[t].set(e,n,r);return}typeof i[t]=="string"&&(t=i[t])}else t===""&&(t="cssText",n="");r[t]=n}},getStyle:function(e,t,n){n=n||e.style;var r=d.CUSTOM_STYLES,i="";if(n){if(t in r){if(r[t].get)return r[t].get(e,t,n);typeof r[t]=="string"&&(t=r[t])}i=n[t],i===""&&(i=d[f](e,t))}return i},setStyles:function(t,n){var r=t.style;e.each(n,function(e,n){d.setStyle(t,n,e,r)},d)},getComputedStyle:function(e,t){var s="",o=e[r],u;return e[i]&&o[n]&&o[n][f]&&(u=o[n][f](e,null),u&&(s=u[t])),s}}),h[t][i][o]!==p?d.CUSTOM_STYLES[s]=o:h[t][i][u]!==p&&(d.CUSTOM_STYLES[s]=u),e.UA.opera&&(d[f]=function(t,i){var s=t[r][n],o=s[f](t,"")[i];return y.test(i)&&(o=e.Color.toRGB(o)),o}),e.UA.webkit&&(d[f]=function(e,t){var i=e[r][n],s=i[f](e,"")[t];return s==="rgba(0, 0, 0, 0)"&&(s=a),s}),e.DOM._getAttrOffset=function(t,n){var r=e.DOM[f](t,n),i=t.offsetParent,s,o,u;return r==="auto"&&(s=e.DOM.getStyle(t,"position"),s==="static"||s==="relative"?r=0:i&&i[l]&&(o=i[l]()[n],u=t[l]()[n],n==="left"||n==="top"?r=u-o:r=o-t[l]()[n])),r},e.DOM._getOffset=function(e){var t,n=null;return e&&(t=d.getStyle(e,"position"),n=[parseInt(d[f](e,"left"),10),parseInt(d[f](e,"top"),10)],isNaN(n[0])&&(n[0]=parseInt(d.getStyle(e,"left"),10),isNaN(n[0])&&(n[0]=t==="relative"?0:e.offsetLeft||0)),isNaN(n[1])&&(n[1]=parseInt(d.getStyle(e,"top"),10),isNaN(n[1])&&(n[1]=t==="relative"?0:e.offsetTop||0))),n},d.CUSTOM_STYLES.transform={set:function(e,t,n){n[v]=t},get:function(e,t){return d[f](e,v)}},d.CUSTOM_STYLES.transformOrigin={set:function(e,t,n){n[m]=t},get:function(e,t){return d[f](e,m)}}})(e),function(e){var t=parseInt,n=RegExp;e.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(r){return e.Color.re_RGB.test(r)||(r=e.Color.toHex(r)),e.Color.re_hex.exec(r)&&(r="rgb("+[t(n.$1,16),t(n.$2,16),t(n.$3,16)].join(", ")+")"),r},toHex:function(t){t=e.Color.KEYWORDS[t]||t;if(e.Color.re_RGB.exec(t)){t=[Number(n.$1).toString(16),Number(n.$2).toString(16),Number(n.$3).toString(16)];for(var r=0;r<t.length;r++)t[r].length<2&&(t[r]="0"+t[r]);t=t.join("")}return t.length<6&&(t=t.replace(e.Color.re_hex3,"$1$1")),t!=="transparent"&&t.indexOf("#")<0&&(t="#"+t),t.toUpperCase()}}}(e)},"3.7.3",{requires:["dom-base"]});
diff --git a/js/yui3/dump/dump-min.js b/js/yui3/dump/dump-min.js
new file mode 100644
index 000000000..7d607be82
--- /dev/null
+++ b/js/yui3/dump/dump-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("dump",function(e,t){var n=e.Lang,r="{...}",i="f(){...}",s=", ",o=" => ",u=function(e,t){var u,a,f=[],l=n.type(e);if(!n.isObject(e))return e+"";if(l=="date")return e;if(e.nodeType&&e.tagName)return e.tagName+"#"+e.id;if(e.document&&e.navigator)return"window";if(e.location&&e.body)return"document";if(l=="function")return i;t=n.isNumber(t)?t:3;if(l=="array"){f.push("[");for(u=0,a=e.length;u<a;u+=1)n.isObject(e[u])?f.push(t>0?n.dump(e[u],t-1):r):f.push(e[u]),f.push(s);f.length>1&&f.pop(),f.push("]")}else if(l=="regexp")f.push(e.toString());else{f.push("{");for(u in e)if(e.hasOwnProperty(u))try{f.push(u+o),n.isObject(e[u])?f.push(t>0?n.dump(e[u],t-1):r):f.push(e[u]),f.push(s)}catch(c){f.push("Error: "+c.message)}f.length>1&&f.pop(),f.push("}")}return f.join("")};e.dump=u,n.dump=u},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/editor-base/editor-base-min.js b/js/yui3/editor-base/editor-base-min.js
new file mode 100644
index 000000000..78b83a8f7
--- /dev/null
+++ b/js/yui3/editor-base/editor-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-base",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r=":last-child",i="body";e.extend(n,e.Base,{frame:null,initializer:function(){var t=(new e.Frame({designMode:!0,title:n.STRINGS.title,use:n.USE,dir:this.get("dir"),extracss:this.get("extracss"),linkedcss:this.get("linkedcss"),defaultblock:this.get("defaultblock"),host:this})).plug(e.Plugin.ExecCommand);t.after("ready",e.bind(this._afterFrameReady,this)),t.addTarget(this),this.frame=t,this.publish("nodeChange",{emitFacade:!0,bubbles:!0,defaultFn:this._defNodeChangeFn})},destructor:function(){this.frame.destroy(),this.detachAll()},copyStyles:function(t,n){if(t.test("a"))return;var r=["color","fontSize","fontFamily","backgroundColor","fontStyle"],i={};e.each(r,function(e){i[e]=t.getStyle(e)}),t.ancestor("b,strong")&&(i.fontWeight="bold"),t.ancestor("u")&&(i.textDecoration||(i.textDecoration="underline")),n.setStyles(i)},_lastBookmark:null,_resolveChangedNode:function(e){var t=this.getInstance(),n,s,o,u;e&&e.test(i)&&(u=new t.EditorSelection,u&&u.anchorNode&&(e=u.anchorNode));if(t&&e&&e.test("html")){n=t.one(i).one(r);while(!o)n?(s=n.one(r),s?n=s:o=!0):o=!0;n&&(n.test("br")&&(n.previous()?n=n.previous():n=n.get("parentNode")),n&&(e=n))}return e||(e=t.one(i)),e},_defNodeChangeFn:function(t){var r=(new Date).getTime(),i=this.getInstance(),s,o,u,a={},f,l,c=[],h="",p="",d,v=!1;if(e.UA.ie)try{s=i.config.doc.selection.createRange(),s.getBookmark&&(this._lastBookmark=s.getBookmark())}catch(m){}t.changedNode=this._resolveChangedNode(t.changedNode);switch(t.changedType){case"tab":!t.changedNode.test("li, li *")&&!t.changedEvent.shiftKey&&(t.changedEvent.frameEvent.preventDefault(),e.UA.webkit?this.execCommand("inserttext"," "):e.UA.gecko?this.frame.exec._command("inserthtml",n.TABKEY):e.UA.ie&&this.execCommand("inserthtml",n.TABKEY));break;case"backspace-up":e.UA.webkit&&t.changedNode&&t.changedNode.set("innerHTML",t.changedNode.get("innerHTML"))}e.UA.webkit&&t.commands&&(t.commands.indent||t.commands.outdent)&&(d=i.all(".webkit-indent-blockquote, blockquote"),d.size()&&d.setStyle("margin","")),o=this.getDomPath(t.changedNode,!1),t.commands&&(a=t.commands),e.each(o,function(t){var r=t.tagName.toLowerCase(),s=n.TAG2CMD[r],o,u,d,m,g;s&&(a[s]=1),o=t.currentStyle||t.style,""+o.fontWeight=="normal"&&(v=!0),""+o.fontWeight=="bold"&&(a.bold=1),e.UA.ie&&o.fontWeight>400&&(a.bold=1),o.fontStyle==="italic"&&(a.italic=1),o.textDecoration.indexOf("underline")>-1&&(a.underline=1),o.textDecoration.indexOf("line-through")>-1&&(a.strikethrough=1),u=i.one(t),u.getStyle("fontFamily")&&(d=u.getStyle("fontFamily").split(",")[0].toLowerCase(),d&&(f=d),f&&(f=f.replace(/'/g,"").replace(/"/g,""))),l=n.NORMALIZE_FONTSIZE(u),m=t.className.split(" "),e.each(m,function(e){e!==""&&e.substr(0,4)!=="yui_"&&c.push(e)}),h=n.FILTER_RGB(u.getStyle("color")),g=n.FILTER_RGB(o.backgroundColor),g!=="transparent"&&g!==""&&(p=g)}),v&&(delete a.bold,delete a.italic),t.dompath=i.all(o),t.classNames=c,t.commands=a,t.fontFamily||(t.fontFamily=f),t.fontSize||(t.fontSize=l),t.fontColor||(t.fontColor=h),t.backgroundColor||(t.backgroundColor=p),u=(new Date).getTime()},getDomPath:function(e,t){var n=[],r,i=this.frame.getInstance();r=i.Node.getDOMNode(e);while(r!==null){if(r===i.config.doc.documentElement||r===i.config.doc||!r.tagName){r=null;break}if(!i.DOM.inDoc(r)){r=null;break}r.nodeName&&r.nodeType&&r.nodeType===1&&n.push(r);if(r===i.config.doc.body){r=null;break}r=r.parentNode}return n.length===0&&(n[0]=i.config.doc.body),t?i.all(n.reverse()):n.reverse()},_afterFrameReady:function(){var t=this.frame.getInstance();this.frame.on("dom:mouseup",e.bind(this._onFrameMouseUp,this)),this.frame.on("dom:mousedown",e.bind(this._onFrameMouseDown,this)),this.frame.on("dom:keydown",e.bind(this._onFrameKeyDown,this)),e.UA.ie&&(this.frame.on("dom:activate",e.bind(this._onFrameActivate,this)),this.frame.on("dom:beforedeactivate",e.bind(this._beforeFrameDeactivate,this))),this.frame.on("dom:keyup",e.bind(this._onFrameKeyUp,this)),this.frame.on("dom:keypress",e.bind(this._onFrameKeyPress,this)),this.frame.on("dom:paste",e.bind(this._onPaste,this)),t.EditorSelection.filter(),this.fire("ready")},_beforeFrameDeactivate:function(e){if(e.frameTarget.test("html"))return;var t=this.getInstance(),n=t.config.doc.selection.createRange();n.compareEndPoints&&!n.compareEndPoints("StartToEnd",n)&&n.pasteHTML('<var id="yui-ie-cursor">')},_onFrameActivate:function(e){if(e.frameTarget.test("html"))return;var t=this.getInstance(),n=new t.EditorSelection,r=n.createRange(),i=t.all("#yui-ie-cursor");i.size()&&i.each(function(e){e.set("id","");if(r.moveToElementText)try{r.moveToElementText(e._node);var t=r.move("character",-1);t===-1&&r.move("character",1),r.select(),r.text=""}catch(n){}e.remove()})},_onPaste:function(e){this.fire("nodeChange",{changedNode:e.frameTarget,changedType:"paste",changedEvent:e.frameEvent})},_onFrameMouseUp:function(e){this.fire("nodeChange",{changedNode:e.frameTarget,changedType:"mouseup",changedEvent:e.frameEvent})},_onFrameMouseDown:function(e){this.fire("nodeChange",{changedNode:e.frameTarget,changedType:"mousedown",changedEvent:e.frameEvent})},_currentSelection:null,_currentSelectionTimer:null,_currentSelectionClear:null,_onFrameKeyDown:function(t){var r,i;this._currentSelection?i=this._currentSelection:(this._currentSelectionTimer&&this._currentSelectionTimer.cancel(),this._currentSelectionTimer=e.later(850,this,function(){this._currentSelectionClear=!0}),r=this.frame.getInstance(),i=new r.EditorSelection(t),this._currentSelection=i),r=this.frame.getInstance(),i=new r.EditorSelection,this._currentSelection=i,i&&i.anchorNode&&(this.fire("nodeChange",{changedNode:i.anchorNode,changedType:"keydown",changedEvent:t.frameEvent}),n.NC_KEYS[t.keyCode]&&(this.fire("nodeChange",{changedNode:i.anchorNode,changedType:n.NC_KEYS[t.keyCode],changedEvent:t.frameEvent}),this.fire("nodeChange",{changedNode:i.anchorNode,changedType:n.NC_KEYS[t.keyCode]+"-down",changedEvent:t.frameEvent})))},_onFrameKeyPress:function(e){var t=this._currentSelection;t&&t.anchorNode&&(this.fire("nodeChange",{changedNode:t.anchorNode,changedType:"keypress",changedEvent:e.frameEvent}),n.NC_KEYS[e.keyCode]&&this.fire("nodeChange",{changedNode:t.anchorNode,changedType:n.NC_KEYS[e.keyCode]+"-press",changedEvent:e.frameEvent}))},_onFrameKeyUp:function(e){var t=this.frame.getInstance(),r=new t.EditorSelection(e);r&&r.anchorNode&&(this.fire("nodeChange",{changedNode:r.anchorNode,changedType:"keyup",selection:r,changedEvent:e.frameEvent}),n.NC_KEYS[e.keyCode]&&this.fire("nodeChange",{changedNode:r.anchorNode,changedType:n.NC_KEYS[e.keyCode]+"-up",selection:r,changedEvent:e.frameEvent})),this._currentSelectionClear&&(this._currentSelectionClear=this._currentSelection=null)},execCommand:function(e,t){var n=this.frame.execCommand(e,t),r=this.frame.getInstance(),i=new r.EditorSelection,s={},o={changedNode:i.anchorNode,changedType:"execcommand",nodes:n};switch(e){case"forecolor":o.fontColor=t;break;case"backcolor":o.backgroundColor=t;break;case"fontsize":o.fontSize=t;break;case"fontname":o.fontFamily=t}return s[e]=1,o.commands=s,this.fire("nodeChange",o),n},getInstance:function(){return this.frame.getInstance()},render:function(e){return this.frame.set("content",this.get("content")),this.frame.render(e),this},focus:function(e){return this.frame.focus(e),this},show:function(){return this.frame.show(),this},hide:function(){return this.frame.hide(),this},getContent:function(){var e="",t=this.getInstance();return t&&t.EditorSelection&&(e=t.EditorSelection.unfilter()),e=e.replace(/ _yuid="([^>]*)"/g,""),e}},{NORMALIZE_FONTSIZE:function(e){var t=e.getStyle("fontSize"),n=t;switch(t){case"-webkit-xxx-large":t="48px";break;case"xx-large":t="32px";break;case"x-large":t="24px";break;case"large":t="18px";break;case"medium":t="16px";break;case"small":t="13px";break;case"x-small":t="10px"}return n!==t&&e.setStyle("fontSize",t),t},TABKEY:'<span class="tab">&nbsp;&nbsp;&nbsp;&nbsp;</span>',FILTER_RGB:function(e){if(e.toLowerCase().indexOf("rgb")!==-1){var t=new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)","gi"),n=e.replace(t,"$1,$2,$3,$4,$5").split(","),r,i,s;n.length===5&&(r=parseInt(n[1],10).toString(16),i=parseInt(n[2],10).toString(16),s=parseInt(n[3],10).toString(16),r=r.length===1?"0"+r:r,i=i.length===1?"0"+i:i,s=s.length===1?"0"+s:s,e="#"+r+i+s)}return e},TAG2CMD:{b:"bold",strong:"bold",i:"italic",em:"italic",u:"underline",sup:"superscript",sub:"subscript",img:"insertimage",a:"createlink",ul:"insertunorderedlist",ol:"insertorderedlist"},NC_KEYS:{8:"backspace",9:"tab",13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",46:"delete"},USE:["substitute","node","selector-css3","editor-selection","stylesheet"],NAME:"editorBase",STRINGS:{title:"Rich Text Editor"},ATTRS:{content:{value:'<br class="yui-cursor">',setter:function(t){return t.substr(0,1)==="\n"&&(t=t.substr(1)),t===""&&(t='<br class="yui-cursor">'),t===" "&&e.UA.gecko&&(t='<br class="yui-cursor">'),this.frame.set("content",t)},getter:function(){return this.frame.get("content")}},dir:{writeOnce:!0,value:"ltr"},linkedcss:{value:"",setter:function(e){return this.frame&&this.frame.set("linkedcss",e),e}},extracss:{value:!1,setter:function(e){return this.frame&&this.frame.set("extracss",e),e}},defaultblock:{value:"p"}}}),e.EditorBase=n},"3.7.3",{requires:["base","frame","node","exec-command","editor-selection"]});
diff --git a/js/yui3/editor-bidi/editor-bidi-min.js b/js/yui3/editor-bidi/editor-bidi-min.js
new file mode 100644
index 000000000..d2c95781c
--- /dev/null
+++ b/js/yui3/editor-bidi/editor-bidi-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-bidi",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host",i="dir",s="BODY",o="nodeChange",u="bidiContextChange",a="style";e.extend(n,e.Base,{lastDirection:null,firstEvent:null,_checkForChange:function(){var e=this.get(r),t=e.getInstance(),i=new t.EditorSelection,s,o;i.isCollapsed?(s=n.blockParent(i.focusNode),s&&(o=s.getStyle("direction"),o!==this.lastDirection&&(e.fire(u,{changedTo:o}),this.lastDirection=o))):(e.fire(u,{changedTo:"select"}),this.lastDirection=null)},_afterNodeChange:function(e){if(this.firstEvent||n.EVENTS[e.changedType])this._checkForChange(),this.firstEvent=!1},_afterMouseUp:function(){this._checkForChange(),this.firstEvent=!1},initializer:function(){var t=this.get(r);this.firstEvent=!0,t.after(o,e.bind(this._afterNodeChange,this)),t.after("dom:mouseup",e.bind(this._afterMouseUp,this))}},{EVENTS:{"backspace-up":!0,"pageup-up":!0,"pagedown-down":!0,"end-up":!0,"home-up":!0,"left-up":!0,"up-up":!0,"right-up":!0,"down-up":!0,"delete-up":!0},BLOCKS:e.EditorSelection.BLOCKS,DIV_WRAPPER:"<DIV></DIV>",blockParent:function(t,r){var i=t,o,u;return i||(i=e.one(s)),i.test(n.BLOCKS)||(i=i.ancestor(n.BLOCKS)),r&&i.test(s)&&(o=e.Node.create(n.DIV_WRAPPER),i.get("children").each(function(e,t){t===0?u=e:o.append(e)}),u.replace(o),o.prepend(u),i=o),i},_NODE_SELECTED:"bidiSelected",addParents:function(e){var t,r,i;tester=function(e){if(!e.getData(n._NODE_SELECTED))return i=!1,!0};for(t=0;t<e.length;t+=1)e[t].setData(n._NODE_SELECTED,!0);for(t=0;t<e.length;t+=1)r=e[t].get("parentNode"),!r.test(s)&&!r.getData(n._NODE_SELECTED)&&(i=!0,r.get("children").some(tester),i&&(e.push(r),r.setData(n._NODE_SELECTED,!0)));for(t=0;t<e.length;t+=1)e[t].clearData(n._NODE_SELECTED);return e},NAME:"editorBidi",NS:"editorBidi",ATTRS:{host:{value:!1}},RE_TEXT_ALIGN:/text-align:\s*\w*\s*;/,removeTextAlign:function(e){return e&&(e.getAttribute(a).match(n.RE_TEXT_ALIGN)&&e.setAttribute(a,e.getAttribute(a).replace(n.RE_TEXT_ALIGN,"")),e.hasAttribute("align")&&e.removeAttribute("align")),e}}),e.namespace("Plugin"),e.Plugin.EditorBidi=n,e.Plugin.ExecCommand.COMMANDS.bidi=function(t,s){var o=this.getInstance(),u=new o.EditorSelection,a=this.get(r).get(r).editorBidi,f,l,c,h,p,d;if(!a){e.error("bidi execCommand is not available without the EditorBiDi plugin.");return}return o.EditorSelection.filterBlocks(),u.isCollapsed?(l=n.blockParent(u.anchorNode),l||(l=o.one("body").one(o.EditorSelection.BLOCKS)),l=n.removeTextAlign(l),s||(d=l.getAttribute(i),!d||d==="ltr"?s="rtl":s="ltr"),l.setAttribute(i,s),e.UA.ie&&(c=l.all("br.yui-cursor"),c.size()===1&&l.get("childNodes").size()===1&&c.remove()),f=l):(h=u.getSelected(),p=[],h.each(function(e){p.push(n.blockParent(e))}),p=o.all(n.addParents(p)),p.each(function(e){var t=s;e=n.removeTextAlign(e),t||(d=e.getAttribute(i),!d||d==="ltr"?t="rtl":t="ltr"),e.setAttribute(i,t)}),f=p),a._checkForChange(),f}},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/editor-br/editor-br-min.js b/js/yui3/editor-br/editor-br-min.js
new file mode 100644
index 000000000..ab4d5a8a3
--- /dev/null
+++ b/js/yui3/editor-br/editor-br-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-br",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host",i="li";e.extend(n,e.Base,{_onKeyDown:function(t){if(t.stopped){t.halt();return}if(t.keyCode===13){var n=this.get(r),s=n.getInstance(),o=new s.EditorSelection;o&&(e.UA.ie&&(!o.anchorNode||!o.anchorNode.test(i)&&!o.anchorNode.ancestor(i))&&(n.execCommand("inserthtml",s.EditorSelection.CURSOR),t.halt()),e.UA.webkit&&!o.anchorNode.test(i)&&!o.anchorNode.ancestor(i)&&(n.frame._execCommand("insertlinebreak",null),t.halt()))}},_afterEditorReady:function(){var t=this.get(r).getInstance();try{t.config.doc.execCommand("insertbronreturn",null,!0)}catch(n){}(e.UA.ie||e.UA.webkit)&&t.on("keydown",e.bind(this._onKeyDown,this),t.config.doc)},_onNodeChange:function(e){switch(e.changedType){case"backspace-up":case"backspace-down":case"delete-up":var t=this.get(r).getInstance(),n=e.changedNode,i=t.config.doc.createTextNode(" ");n.appendChild(i),n.removeChild(i)}},initializer:function(){var t=this.get(r);if(t.editorPara){e.error("Can not plug EditorBR and EditorPara at the same time.");return}t.after("ready",e.bind(this._afterEditorReady,this)),e.UA.gecko&&t.on("nodeChange",e.bind(this._onNodeChange,this))}},{NAME:"editorBR",NS:"editorBR",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorBR=n},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/editor-lists/editor-lists-min.js b/js/yui3/editor-lists/editor-lists-min.js
new file mode 100644
index 000000000..9bc04dcc4
--- /dev/null
+++ b/js/yui3/editor-lists/editor-lists-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-lists",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="li",i="ol",s="ul",o="host";e.extend(n,e.Base,{_onNodeChange:function(t){var u=this.get(o).getInstance(),a,f,l,c,h=!1,p,d=!1;t.changedType==="tab"&&(t.changedNode.test(r+", "+r+" *")&&(t.changedEvent.halt(),t.preventDefault(),a=t.changedNode,l=t.changedEvent.shiftKey,c=a.ancestor(i+","+s),p=s,c.get("tagName").toLowerCase()===i&&(p=i),a.test(r)||(a=a.ancestor(r)),l?a.ancestor(r)&&(a.ancestor(r).insert(a,"after"),h=!0,d=!0):a.previous(r)&&(f=u.Node.create("<"+p+"></"+p+">"),a.previous(r).append(f),f.append(a),h=!0)),h&&(a.test(r)||(a=a.ancestor(r)),a.all(n.REMOVE).remove(),e.UA.ie&&(a=a.append(n.NON).one(n.NON_SEL)),(new u.EditorSelection).selectNode(a,!0,d)))},initializer:function(){this.get(o).on("nodeChange",e.bind(this._onNodeChange,this))}},{NON:'<span class="yui-non">&nbsp;</span>',NON_SEL:"span.yui-non",REMOVE:"br",NAME:"editorLists",NS:"lists",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorLists=n},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/editor-para-base/editor-para-base-min.js b/js/yui3/editor-para-base/editor-para-base-min.js
new file mode 100644
index 000000000..4e6ea7cb2
--- /dev/null
+++ b/js/yui3/editor-para-base/editor-para-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-para-base",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host",i="body",s=i+" > p",o="p",u="<br>";e.extend(n,e.Base,{_fixFirstPara:function(){var e=this.get(r),t=e.getInstance(),n,i,a=t.config.doc.body,f=a.innerHTML,l=f.length?!0:!1;f===u&&(f="",l=!1),a.innerHTML="<"+o+">"+f+t.EditorSelection.CURSOR+"</"+o+">",i=t.one(s),n=new t.EditorSelection,n.selectNode(i,!0,l)},_afterEditorReady:function(){var e=this.get(r),t=e.getInstance(),n;t&&(t.EditorSelection.filterBlocks(),n=t.EditorSelection.DEFAULT_BLOCK_TAG,s=i+" > "+n,o=n)},_afterContentChange:function(){var e=this.get(r),t=e.getInstance();t&&t.EditorSelection&&t.EditorSelection.filterBlocks()},_afterPaste:function(){var t=this.get(r),n=t.getInstance();e.later(50,t,function(){n.EditorSelection.filterBlocks()})},initializer:function(){var t=this.get(r);if(t.editorBR){e.error("Can not plug EditorPara and EditorBR at the same time.");return}t.after("ready",e.bind(this._afterEditorReady,this)),t.after("contentChange",e.bind(this._afterContentChange,this)),e.Env.webkit&&t.after("dom:paste",e.bind(this._afterPaste,this))}},{NAME:"editorParaBase",NS:"editorParaBase",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorParaBase=n},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/editor-para-ie/editor-para-ie-min.js b/js/yui3/editor-para-ie/editor-para-ie-min.js
new file mode 100644
index 000000000..040bab6b8
--- /dev/null
+++ b/js/yui3/editor-para-ie/editor-para-ie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-para-ie",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host",i="nodeChange",s="p";e.extend(n,e.Plugin.EditorParaBase,{_onNodeChange:function(e){var t=this.get(r),n=t.getInstance(),i=n.EditorSelection.DEFAULT_BLOCK_TAG,o,u=":last-child",a,f,l,c,h,p=!1;switch(e.changedType){case"enter-up":a=this._lastPara?this._lastPara:e.changedNode,f=a.one("br.yui-cursor"),this._lastPara&&delete this._lastPara,f&&(f.previous()||f.next())&&f.ancestor(s)&&f.remove(),a.test(i)||(l=a.ancestor(i),l&&(a=l,l=null));if(a.test(i)){o=a.previous();if(o){c=o.one(u);while(!p)c?(h=c.one(u),h?c=h:p=!0):p=!0;c&&t.copyStyles(c,a)}}break;case"enter":e.changedNode.test("br")?e.changedNode.remove():e.changedNode.test("p, span")&&(f=e.changedNode.one("br.yui-cursor"),f&&f.remove())}},initializer:function(){var t=this.get(r);if(t.editorBR){e.error("Can not plug EditorPara and EditorBR at the same time.");return}t.on(i,e.bind(this._onNodeChange,this))}},{NAME:"editorPara",NS:"editorPara",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorPara=n},"3.7.3",{requires:["editor-para-base"]});
diff --git a/js/yui3/editor-para/editor-para-min.js b/js/yui3/editor-para/editor-para-min.js
new file mode 100644
index 000000000..813da3109
--- /dev/null
+++ b/js/yui3/editor-para/editor-para-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-para",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host",i="body",s="nodeChange",o="parentNode",u=i+" > p",a="p",f="<br>",l="firstChild",c="li";e.extend(n,e.Plugin.EditorParaBase,{_onNodeChange:function(t){var n=this.get(r),s=n.getInstance(),h,p,d,v,m,g=s.EditorSelection.DEFAULT_BLOCK_TAG,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D,H=":last-child",B,j,F,I,q,R=!1,U;switch(t.changedType){case"enter-up":B=this._lastPara?this._lastPara:t.changedNode,j=B.one("br.yui-cursor"),this._lastPara&&delete this._lastPara,j&&(j.previous()||j.next())&&j.ancestor(a)&&j.remove(),B.test(g)||(C=B.ancestor(g),C&&(B=C,C=null));if(B.test(g)){k=B.previous();if(k){I=k.one(H);while(!R)I?(q=I.one(H),q?I=q:R=!0):R=!0;I&&n.copyStyles(I,B)}}break;case"enter":e.UA.webkit&&t.changedEvent.shiftKey&&(n.execCommand("insertbr"),t.changedEvent.preventDefault()),t.changedNode.test("li")&&!e.UA.ie&&(h=s.EditorSelection.getText(t.changedNode),h===""&&(d=t.changedNode.ancestor("ol,ul"),F=d.getAttribute("dir"),F!==""&&(F=' dir = "'+F+'"'),d=t.changedNode.ancestor(s.EditorSelection.BLOCKS),v=s.Node.create("<p"+F+">"+s.EditorSelection.CURSOR+"</p>"),d.insert(v,"after"),t.changedNode.remove(),t.changedEvent.halt(),m=new s.EditorSelection,m.selectNode(v,!0,!1)));if(e.UA.gecko&&n.get("defaultblock")!=="p"){d=t.changedNode;if(!d.test(c)&&!d.ancestor(c)){d.test(g)||(d=d.ancestor(g)),v=s.Node.create("<"+g+"></"+g+">"),d.insert(v,"after"),m=new s.EditorSelection;if(m.anchorOffset){y=m.anchorNode.get("textContent"),p=s.one(s.config.doc.createTextNode(y.substr(0,m.anchorOffset))),b=s.one(s.config.doc.createTextNode(y.substr(m.anchorOffset))),E=m.anchorNode,E.setContent(""),S=E.cloneNode(),S.append(b),x=!1,N=E;while(!x)N=N.get(o),N&&!N.test(g)?(T=N.cloneNode(),T.set("innerHTML",""),T.append(S),w=N.get("childNodes"),U=!1,w.each(function(e){U&&T.append(e),e===E&&(U=!0)}),E=N,S=T):x=!0;b=S,m.anchorNode.append(p),b&&v.append(b)}v.get(l)&&(v=v.get(l)),v.prepend(s.EditorSelection.CURSOR),m.focusCursor(!0,!0),h=s.EditorSelection.getText(v),h!==""&&s.EditorSelection.cleanCursor(),t.changedEvent.preventDefault()}}break;case"keyup":e.UA.gecko&&s.config.doc&&s.config.doc.body&&s.config.doc.body.innerHTML.length<20&&(s.one(u)||this._fixFirstPara());break;case"backspace-up":case"backspace-down":case"delete-up":e.UA.ie||(L=s.all(u),O=s.one(i),L.item(0)&&(O=L.item(0)),A=O.one("br"),A&&(A.removeAttribute("id"),A.removeAttribute("class")),p=s.EditorSelection.getText(O),p=p.replace(/ /g,"").replace(/\n/g,""),_=O.all("img"),p.length===0&&!_.size()&&(O.test(a)||this._fixFirstPara(),M=null,t.changedNode&&t.changedNode.test(a)&&(M=t.changedNode),!M&&n._lastPara&&n._lastPara.inDoc()&&(M=n._lastPara),M&&!M.test(a)&&(M=M.ancestor(a)),M&&!M.previous()&&M.get(o)&&M.get(o).test(i)&&(t.changedEvent.frameEvent.halt(),t.preventDefault())),e.UA.webkit&&t.changedNode&&(t.preventDefault(),O=t.changedNode,O.test("li")&&!O.previous()&&!O.next()&&(h=O.get("innerHTML").replace(f,""),h===""&&O.get(o)&&(O.get(o).replace(s.Node.create(f)),t.changedEvent.frameEvent.halt(),s.EditorSelection.filterBlocks())))),e.UA.gecko&&(v=t.changedNode,D=s.config.doc.createTextNode(" "),v.appendChild(D),v.removeChild(D))}e.UA.gecko&&t.changedNode&&!t.changedNode.test(g)&&(M=t.changedNode.ancestor(g),M&&(this._lastPara=M))},initializer:function(){var t=this.get(r);if(t.editorBR){e.error("Can not plug EditorPara and EditorBR at the same time.");return}t.on(s,e.bind(this._onNodeChange,this))}},{NAME:"editorPara",NS:"editorPara",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorPara=n},"3.7.3",{requires:["editor-para-base"]});
diff --git a/js/yui3/editor-selection/editor-selection-min.js b/js/yui3/editor-selection/editor-selection-min.js
new file mode 100644
index 000000000..aa4f651f6
--- /dev/null
+++ b/js/yui3/editor-selection/editor-selection-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-selection",function(e,t){var n="textContent",r="innerHTML",i="fontFamily";e.UA.ie&&(n="nodeValue"),e.EditorSelection=function(t){var n,r,i,s,o,u,a,f=0,l,c;e.config.win.getSelection&&(!e.UA.ie||e.UA.ie<9)?n=e.config.win.getSelection():e.config.doc.selection&&(n=e.config.doc.selection.createRange()),this._selection=n;if(!n)return!1;if(n.pasteHTML){this.isCollapsed=n.compareEndPoints("StartToEnd",n)?!1:!0;if(this.isCollapsed){this.anchorNode=this.focusNode=e.one(n.parentElement()),t&&(i=e.config.doc.elementFromPoint(t.clientX,t.clientY)),o=n.duplicate();if(!i){r=n.parentElement(),s=r.childNodes;for(u=0;u<s.length;u++)o.inRange(n)&&(i||(i=s[u]))}this.ieNode=i,i&&(i.nodeType!==3&&(i.firstChild&&(i=i.firstChild),i&&i.tagName&&i.tagName.toLowerCase()==="body"&&i.firstChild&&(i=i.firstChild)),this.anchorNode=this.focusNode=e.EditorSelection.resolve(i),o.moveToElementText(n.parentElement()),a=n.compareEndPoints("StartToStart",o),a&&(f=Math.abs(n.move("character",-9999))),this.anchorOffset=this.focusOffset=f,this.anchorTextNode=this.focusTextNode=e.one(i))}else n.htmlText&&n.htmlText!==""&&(l=e.Node.create(n.htmlText),l&&l.get("id")?(c=l.get("id"),this.anchorNode=this.focusNode=e.one("#"+c)):l&&(l=l.get("childNodes"),this.anchorNode=this.focusNode=l.item(0)))}else this.isCollapsed=n.isCollapsed,this.anchorNode=e.EditorSelection.resolve(n.anchorNode),this.focusNode=e.EditorSelection.resolve(n.focusNode),this.anchorOffset=n.anchorOffset,this.focusOffset=n.focusOffset,this.anchorTextNode=e.one(n.anchorNode),this.focusTextNode=e.one(n.focusNode);e.Lang.isString(n.text)?this.text=n.text:n.toString?this.text=n.toString():this.text=""},e.EditorSelection.removeFontFamily=function(t){t.removeAttribute("face");var n=t.getAttribute("style").toLowerCase();(n===""||n==="font-family: ")&&t.removeAttribute("style"),n.match(e.EditorSelection.REG_FONTFAMILY)&&(n=n.replace(e.EditorSelection.REG_FONTFAMILY,""),t.setAttribute("style",n))},e.EditorSelection.filter=function(t){var n=(new Date).getTime(),r,s=e.all(e.EditorSelection.ALL),o=e.all("strong,em"),u=e.config.doc,a,f={},l="",c,h=(new Date).getTime(),p;s.each(function(t){var n=e.Node.getDOMNode(t);n.style[i]&&(f["."+t._yuid]=n.style[i],t.addClass(t._yuid),e.EditorSelection.removeFontFamily(n))}),p=(new Date).getTime(),e.all(".hr").addClass("yui-skip").addClass("yui-non"),e.UA.ie&&(a=u.getElementsByTagName("hr"),e.each(a,function(e){var t=u.createElement("div"),n=t.style;t.className="hr yui-non yui-skip",t.setAttribute("readonly",!0),t.setAttribute("contenteditable",!1),e.parentNode&&e.parentNode.replaceChild(t,e),n.border="1px solid #ccc",n.lineHeight="0",n.height="0",n.fontSize="0",n.marginTop="5px",n.marginBottom="5px",n.marginLeft="0px",n.marginRight="0px",n.padding="0"})),e.each(f,function(e,t){l+=t+" { font-family: "+e.replace(/"/gi,"")+"; }"}),e.StyleSheet(l,"editor"),o.each(function(t,n){var r=t.get("tagName").toLowerCase(),i="i";r==="strong"&&(i="b"),e.EditorSelection.prototype._swap(o.item(n),i)}),c=e.all("ol,ul"),c.each(function(e){var t=e.all("li");t.size()||e.remove()}),t&&e.EditorSelection.filterBlocks(),r=(new Date).getTime()},e.EditorSelection.filterBlocks=function(){var t=(new Date).getTime(),r,i=e.config.doc.body.childNodes,s,o,u=!1,a=!0,f,l,c,h,p,d;if(i){for(s=0;s<i.length;s++)o=e.one(i[s]),o.test(e.EditorSelection.BLOCKS)?u=e.EditorSelection._wrapBlock(u):(a=!0,i[s].nodeType===3&&(h=i[s][n].match(e.EditorSelection.REG_CHAR),p=i[s][n].match(e.EditorSelection.REG_NON),h===null&&p&&(a=!1)),a&&(u||(u=[]),u.push(i[s])));u=e.EditorSelection._wrapBlock(u)}l=e.all(e.EditorSelection.DEFAULT_BLOCK_TAG);if(l.size()===1){c=l.item(0).all("br");if(c.size()===1){c.item(0).test(".yui-cursor")||c.item(0).remove(),d=l.item(0).get("innerHTML");if(d===""||d===" ")l.set("innerHTML",e.EditorSelection.CURSOR),f=new e.EditorSelection,f.focusCursor(!0,!0);c.item(0).test(".yui-cursor")&&e.UA.ie&&c.item(0).remove()}}else l.each(function(e){var t=e.get("innerHTML");t===""&&e.remove()});r=(new Date).getTime()},e.EditorSelection.REG_FONTFAMILY=/font-family:\s*;/,e.EditorSelection.REG_CHAR=/[a-zA-Z-0-9_!@#\$%\^&*\(\)-=_+\[\]\\{}|;':",.\/<>\?]/gi,e.EditorSelection.REG_NON=/[\s|\n|\t]/gi,e.EditorSelection.REG_NOHTML=/<\S[^><]*>/g,e.EditorSelection._wrapBlock=function(t){if(t){var n=e.Node.create("<"+e.EditorSelection.DEFAULT_BLOCK_TAG+"></"+e.EditorSelection.DEFAULT_BLOCK_TAG+">"),r=e.one(t[0]),i;for(i=1;i<t.length;i++)n.append(t[i]);r.replace(n),n.prepend(r)}return!1},e.EditorSelection.unfilter=function(){var t=e.all("body [class]"),n="",r,s,o=e.one("body");return t.each(function(e){e.hasClass(e._yuid)&&(e.setStyle(i,e.getStyle(i)),e.removeClass(e._yuid),e.getAttribute("class")===""&&e.removeAttribute("class"))}),r=e.all(".yui-non"),r.each(function(e){!e.hasClass("yui-skip")&&e.get("innerHTML")===""?e.remove():e.removeClass("yui-non").removeClass("yui-skip")}),s=e.all("body [id]"),s.each(function(e){e.get("id").indexOf("yui_3_")===0&&(e.removeAttribute("id"),e.removeAttribute("_yuid"))}),o&&(n=o.get("innerHTML")),e.all(".hr").addClass("yui-skip").addClass("yui-non"),n},e.EditorSelection.resolve=function(t){if(t&&t.nodeType===3)try{t=t.parentNode}catch(n){t="body"}return e.one(t)},e.EditorSelection.getText=function(t){var n=t.get("innerHTML").replace(e.EditorSelection.REG_NOHTML,"");return n=n.replace("<span><br></span>","").replace("<br>",""),n},e.EditorSelection.DEFAULT_BLOCK_TAG="p",e.EditorSelection.ALL="[style],font[face]",e.EditorSelection.BLOCKS="p,div,ul,ol,table,style",e.EditorSelection.TMP="yui-tmp",e.EditorSelection.DEFAULT_TAG="span",e.EditorSelection.CURID="yui-cursor",e.EditorSelection.CUR_WRAPID="yui-cursor-wrapper",e.EditorSelection.CURSOR='<span><br class="yui-cursor"></span>',e.EditorSelection.hasCursor=function(){var t=e.all("#"+e.EditorSelection.CUR_WRAPID);return t.size()},e.EditorSelection.cleanCursor=function(){var t,n="br.yui-cursor";t=e.all(n),t.size()&&t.each(function(t){var n=t.get("parentNode.parentNode.childNodes"),r;n.size()?t.remove():(r=e.EditorSelection.getText(n.item(0)),r!==""&&t.remove())})},e.EditorSelection.prototype={text:null,isCollapsed:null,anchorNode:null,anchorOffset:null,anchorTextNode:null,focusNode:null,focusOffset:null,focusTextNode:null,_selection:null,_wrap:function(t,n){var i=e.Node.create("<"+n+"></"+n+">");return i.set(r,t.get(r)),t.set(r,""),t.append(i),e.Node.getDOMNode(i)},_swap:function(t,n){var i=e.Node.create("<"+n+"></"+n+">");return i.set(r,t.get(r)),t.replace(i,t),e.Node.getDOMNode(i)},getSelected:function(){e.EditorSelection.filter(),e.config.doc.execCommand("fontname",null,e.EditorSelection.TMP);var t=e.all(e.EditorSelection.ALL),n=[];return t.each(function(r,s){r.getStyle(i)===e.EditorSelection.TMP&&(r.setStyle(i,""),e.EditorSelection.removeFontFamily(r),r.test("body")||n.push(e.Node.getDOMNode(t.item(s))))}),e.all(n)},insertContent:function(e){return this.insertAtCursor(e,this.anchorTextNode,this.anchorOffset,!0)},insertAtCursor:function(t,r,i,s){var o=e.Node.create("<"+e.EditorSelection.DEFAULT_TAG+' class="yui-non"></'+e.EditorSelection.DEFAULT_TAG+">"),u,a,f,l,c=this.createRange(),h;r&&r.test("body")&&(h=e.Node.create("<span></span>"),r.append(h),r=h);if(c.pasteHTML){if(i===0&&r&&!r.previous()&&r.get("nodeType")===3)return r.insert(t,"before"),c.moveToElementText&&c.moveToElementText(e.Node.getDOMNode(r.previous())),c.collapse(!1),c.select(),r.previous();l=e.Node.create(t);try{c.pasteHTML('<span id="rte-insert"></span>')}catch(p){}u=e.one("#rte-insert");if(u)return u.set("id",""),u.replace(l),c.moveToElementText&&c.moveToElementText(e.Node.getDOMNode(l)),c.collapse(!1),c.select(),l;e.on("available",function(){u.set("id",""),u.replace(l),c.moveToElementText&&c.moveToElementText(e.Node.getDOMNode(l)),c.collapse(!1),c.select()},"#rte-insert")}else i>0?(u=r.get(n),a=e.one(e.config.doc.createTextNode(u.substr(0,i))),f=e.one(e.config.doc.createTextNode(u.substr(i))),r.replace(a,r),l=e.Node.create(t),l.get("nodeType")===11&&(h=e.Node.create("<span></span>"),h.append(l),l=h),a.insert(l,"after"),f&&(l.insert(o,"after"),o.insert(f,"after"),this.selectNode(o,s))):(r.get("nodeType")===3&&(r=r.get("parentNode")),l=e.Node.create(t),t=r.get("innerHTML").replace(/\n/gi,""),t===""||t==="<br>"?r.append(l):l.get("parentNode")?r.insert(l,"before"):e.one("body").prepend(l),r.get("firstChild").test("br")&&r.get("firstChild").remove());return l},wrapContent:function(t){t=t?t:e.EditorSelection.DEFAULT_TAG;if(!this.isCollapsed){var n=this.getSelected(),r=[],i,s,o,u;return n.each(function(e,i){var s=e.get("tagName").toLowerCase();s==="font"?r.push(this._swap(n.item(i),t)):r.push(this._wrap(n.item(i),t))},this),i=this.createRange(),o=r[0],s=r[r.length-1],this._selection.removeAllRanges?(i.setStart(r[0],0),i.setEnd(s,s.childNodes.length),this._selection.removeAllRanges(),this._selection.addRange(i)):(i.moveToElementText&&(i.moveToElementText(e.Node.getDOMNode(o)),u=this.createRange(),u.moveToElementText(e.Node.getDOMNode(s)),i.setEndPoint("EndToEnd",u)),i.select()),r=e.all(r),r}return e.all([])},replace:function(t,r){var i=this.createRange(),s,o,u,a;return i.getBookmark?(u=i.getBookmark(),o=this.anchorNode.get("innerHTML").replace(t,r),this.anchorNode.set("innerHTML",o),i.moveToBookmark(u),a=e.one(i.parentElement())):(s=this.anchorTextNode,o=s.get(n),u=o.indexOf(t),o=o.replace(t,""),s.set(n,o),a=this.insertAtCursor(r,s,u,!0)),a},remove:function(){return this._selection&&this._selection.removeAllRanges&&this._selection.removeAllRanges(),this},createRange:function(){return e.config.doc.selection?e.config.doc.selection.createRange():e.config.doc.createRange()},selectNode:function(t,n,r){if(!t)return;r=r||0,t=e.Node.getDOMNode(t);var i=this.createRange();if(i.selectNode){i.selectNode(t),this._selection.removeAllRanges(),this._selection.addRange(i);if(n)try{this._selection.collapse(t,r)}catch(s){this._selection.collapse(t,0)}}else{t.nodeType===3&&(t=t.parentNode);try{i.moveToElementText(t)}catch(o){}n&&i.collapse(r?!1:!0),i.select()}return this},setCursor:function(){return this.removeCursor(!1),this.insertContent(e.EditorSelection.CURSOR)},getCursor:function(){return e.all("#"+e.EditorSelection.CURID)},removeCursor:function(e){var t=this.getCursor();return t&&(e?(t.removeAttribute("id"),t.set("innerHTML",'<br class="yui-cursor">')):t.remove()),t},focusCursor:function(e,t){e!==!1&&(e=!0),t!==!1&&(t=!0);var n=this.removeCursor(!0);n&&n.each(function(n){this.selectNode(n,e,t)},this)},toString:function(){return"EditorSelection Object"}},e.Selection=e.EditorSelection},"3.7.3",{requires:["node"]});
diff --git a/js/yui3/editor-tab/editor-tab-min.js b/js/yui3/editor-tab/editor-tab-min.js
new file mode 100644
index 000000000..8f6fbc0af
--- /dev/null
+++ b/js/yui3/editor-tab/editor-tab-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("editor-tab",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="host";e.extend(n,e.Base,{_onNodeChange:function(e){var t="indent";e.changedType==="tab"&&(e.changedNode.test("li, li *")||(e.changedEvent.halt(),e.preventDefault(),e.changedEvent.shiftKey&&(t="outdent"),this.get(r).execCommand(t,"")))},initializer:function(){this.get(r).on("nodeChange",e.bind(this._onNodeChange,this))}},{NAME:"editorTab",NS:"tab",ATTRS:{host:{value:!1}}}),e.namespace("Plugin"),e.Plugin.EditorTab=n},"3.7.3",{requires:["editor-base"]});
diff --git a/js/yui3/escape/escape-min.js b/js/yui3/escape/escape-min.js
new file mode 100644
index 000000000..8bab388b9
--- /dev/null
+++ b/js/yui3/escape/escape-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("escape",function(e,t){var n={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;","`":"&#x60;"},r={html:function(e){return(e+"").replace(/[&<>"'\/`]/g,r._htmlReplacer)},regex:function(e){return(e+"").replace(/[\-$\^*()+\[\]{}|\\,.?\s]/g,"\\$&")},_htmlReplacer:function(e){return n[e]}};r.regexp=r.regex,e.Escape=r},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/event-base-ie/event-base-ie-min.js b/js/yui3/event-base-ie/event-base-ie-min.js
new file mode 100644
index 000000000..3deb64fc1
--- /dev/null
+++ b/js/yui3/event-base-ie/event-base-ie-min.js
@@ -0,0 +1,9 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+(function(){var e,t=YUI.Env,n=YUI.config,r=n.doc,i=r&&r.documentElement,s="onreadystatechange",o=n.pollInterval||40;i.doScroll&&!t._ieready&&(t._ieready=function(){t._ready()},
+/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
+self!==self.top?(e=function(){r.readyState=="complete"&&(t.remove(r,s,e),t.ieready())},t.add(r,s,e)):t._dri=setInterval(function(){try{i.doScroll("left"),clearInterval(t._dri),t._dri=null,t._ieready()}catch(e){}},o))})(),YUI.add("event-base-ie",function(e,t){function n(){e.DOM2EventFacade.apply(this,arguments)}function r(t){var n=e.config.doc.createEventObject(t),i=r.prototype;return n.hasOwnProperty=function(){return!0},n.init=i.init,n.halt=i.halt,n.preventDefault=i.preventDefault,n.stopPropagation=i.stopPropagation,n.stopImmediatePropagation=i.stopImmediatePropagation,e.DOM2EventFacade.apply(n,arguments),n}var i=e.config.doc&&e.config.doc.implementation,s=e.config.lazyEventFacade,o={0:1,4:2,2:3},u={mouseout:"toElement",mouseover:"fromElement"},a=e.DOM2EventFacade.resolve,f={init:function(){n.superclass.init.apply(this,arguments);var t=this._event,r,i,s,u,f,l;this.target=a(t.srcElement),"clientX"in t&&!r&&0!==r&&(r=t.clientX,i=t.clientY,s=e.config.doc,u=s.body,f=s.documentElement,r+=f.scrollLeft||u&&u.scrollLeft||0,i+=f.scrollTop||u&&u.scrollTop||0,this.pageX=r,this.pageY=i),t.type=="mouseout"?l=t.toElement:t.type=="mouseover"&&(l=t.fromElement),this.relatedTarget=a(l||t.relatedTarget),this.which=this.button=t.keyCode||o[t.button]||t.button},stopPropagation:function(){this._event.cancelBubble=!0,this._wrapper.stopped=1,this.stopped=1},stopImmediatePropagation:function(){this.stopPropagation(),this._wrapper.stopped=2,this.stopped=2},preventDefault:function(e){this._event.returnValue=e||!1,this._wrapper.prevented=1,this.prevented=1}};e.extend(n,e.DOM2EventFacade,f),e.extend(r,e.DOM2EventFacade,f),r.prototype.init=function(){var e=this._event,t=this._wrapper.overrides,n=r._define,i=r._lazyProperties,s;this.altKey=e.altKey,this.ctrlKey=e.ctrlKey,this.metaKey=e.metaKey,this.shiftKey=e.shiftKey,this.type=t&&t.type||e.type,this.clientX=e.clientX,this.clientY=e.clientY,this.keyCode=this.charCode=e.keyCode,this.which=this.button=e.keyCode||o[e.button]||e.button;for(s in i)i.hasOwnProperty(s)&&n(this,s,i[s]);this._touch&&this._touch(e,this._currentTarget,this._wrapper)},r._lazyProperties={target:function(){return a(this._event.srcElement)},relatedTarget:function(){var e=this._event,t=u[e.type]||"relatedTarget";return a(e[t]||e.relatedTarget)},currentTarget:function(){return a(this._currentTarget)},wheelDelta:function(){var e=this._event;if(e.type==="mousewheel"||e.type==="DOMMouseScroll")return e.detail?e.detail*-1:Math.round(e.wheelDelta/80)||(e.wheelDelta<0?-1:1)},pageX:function(){var t=this._event,n=t.pageX,r,i,s;return n===undefined&&(r=e.config.doc,i=r.body&&r.body.scrollLeft,s=r.documentElement.scrollLeft,n=t.clientX+(s||i||0)),n},pageY:function(){var t=this._event,n=t.pageY,r,i,s;return n===undefined&&(r=e.config.doc,i=r.body&&r.body.scrollTop,s=r.documentElement.scrollTop,n=t.clientY+(s||i||0)),n}},r._define=function(e,t,n){function r(r){var i=arguments.length?r:n.call(this);return delete e[t],Object.defineProperty(e,t,{value:i,configurable:!0,writable:!0}),i}Object.defineProperty(e,t,{get:r,set:r,configurable:!0})};if(i&&!i.hasFeature("Events","2.0")){if(s)try{Object.defineProperty(e.config.doc.createEventObject(),"z",{})}catch(l){s=!1}e.DOMEventFacade=s?r:n}},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/event-base/event-base-min.js b/js/yui3/event-base/event-base-min.js
new file mode 100644
index 000000000..c1fef0d2c
--- /dev/null
+++ b/js/yui3/event-base/event-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+(function(){var e=YUI.Env;e._ready||(e._ready=function(){e.DOMReady=!0,e.remove(YUI.config.doc,"DOMContentLoaded",e._ready)},e.add(YUI.config.doc,"DOMContentLoaded",e._ready))})(),YUI.add("event-base",function(e,t){e.publish("domready",{fireOnce:!0,async:!0}),YUI.Env.DOMReady?e.fire("domready"):e.Do.before(function(){e.fire("domready")},YUI.Env,"_ready");var n=e.UA,r={},i={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9,63272:46,63273:36,63275:35},s=function(t){if(!t)return t;try{t&&3==t.nodeType&&(t=t.parentNode)}catch(n){return null}return e.one(t)},o=function(e,t,n){this._event=e,this._currentTarget=t,this._wrapper=n||r,this.init()};e.extend(o,Object,{init:function(){var e=this._event,t=this._wrapper.overrides,r=e.pageX,o=e.pageY,u,a=this._currentTarget;this.altKey=e.altKey,this.ctrlKey=e.ctrlKey,this.metaKey=e.metaKey,this.shiftKey=e.shiftKey,this.type=t&&t.type||e.type,this.clientX=e.clientX,this.clientY=e.clientY,this.pageX=r,this.pageY=o,u=e.keyCode||e.charCode,n.webkit&&u in i&&(u=i[u]),this.keyCode=u,this.charCode=u,this.which=e.which||e.charCode||u,this.button=this.which,this.target=s(e.target),this.currentTarget=s(a),this.relatedTarget=s(e.relatedTarget);if(e.type=="mousewheel"||e.type=="DOMMouseScroll")this.wheelDelta=e.detail?e.detail*-1:Math.round(e.wheelDelta/80)||(e.wheelDelta<0?-1:1);this._touch&&this._touch(e,a,this._wrapper)},stopPropagation:function(){this._event.stopPropagation(),this._wrapper.stopped=1,this.stopped=1},stopImmediatePropagation:function(){var e=this._event;e.stopImmediatePropagation?e.stopImmediatePropagation():this.stopPropagation(),this._wrapper.stopped=2,this.stopped=2},preventDefault:function(e){var t=this._event;t.preventDefault(),t.returnValue=e||!1,this._wrapper.prevented=1,this.prevented=1},halt:function(e){e?this.stopImmediatePropagation():this.stopPropagation(),this.preventDefault()}}),o.resolve=s,e.DOM2EventFacade=o,e.DOMEventFacade=o,function(){e.Env.evt.dom_wrappers={},e.Env.evt.dom_map={};var t=e.DOM,n=e.Env.evt,r=e.config,i=r.win,s=YUI.Env.add,o=YUI.Env.remove,u=function(){YUI.Env.windowLoaded=!0,e.Event._load(),o(i,"load",u)},a=function(){e.Event._unload()},f="domready",l="~yui|2|compat~",c=function(n){try{return n&&typeof n!="string"&&e.Lang.isNumber(n.length)&&!n.tagName&&!t.isWindow(n)}catch(r){return!1}},h=e.CustomEvent.prototype._delete,p=function(t){var n=h.apply(this,arguments);return this.hasSubs()||e.Event._clean(this),n},d=function(){var r=!1,u=0,h=[],v=n.dom_wrappers,m=null,g=n.dom_map;return{POLL_RETRYS:1e3,POLL_INTERVAL:40,lastError:null,_interval:null,_dri:null,DOMReady:!1,startInterval:function(){d._interval||(d._interval=setInterval(d._poll,d.POLL_INTERVAL))},onAvailable:function(t,n,r,i,s,o){var a=e.Array(t),f,l;for(f=0;f<a.length;f+=1)h.push({id:a[f],fn:n,obj:r,override:i,checkReady:s,compat:o});return u=this.POLL_RETRYS,setTimeout(d._poll,0),l=new e.EventHandle({_delete:function(){if(l.handle){l.handle.detach();return}var e,t;for(e=0;e<a.length;e++)for(t=0;t<h.length;t++)a[e]===h[t].id&&h.splice(t,1)}}),l},onContentReady:function(e,t,n,r,i){return d.onAvailable(e,t,n,r,!0,i)},attach:function(t,n,r,i){return d._attach(e.Array(arguments,0,!0))},_createWrapper:function(t,n,r,o,u){var a,f=e.stamp(t),l="event:"+f+n;return!1===u&&(l+="native"),r&&(l+="capture"),a=v[l],a||(a=e.publish(l,{silent:!0,bubbles:!1,contextFn:function(){return o?a.el:(a.nodeRef=a.nodeRef||e.one(a.el),a.nodeRef)}}),a.overrides={},a.el=t,a.key=l,a.domkey=f,a.type=n,a.fn=function(e){a.fire(d.getEvent(e,t,o||!1===u))},a.capture=r,t==i&&n=="load"&&(a.fireOnce=!0,m=l),a._delete=p,v[l]=a,g[f]=g[f]||{},g[f][l]=a,s(t,n,a.fn,r)),a},_attach:function(n,r){var s,o,u,a,f,h=!1,p,v=n[0],m=n[1],g=n[2]||i,y=r&&r.facade,b=r&&r.capture,w=r&&r.overrides;n[n.length-1]===l&&(s=!0);if(!m||!m.call)return!1;if(c(g))return o=[],e.each(g,function(e,t){n[2]=e,o.push(d._attach(n.slice(),r))}),new e.EventHandle(o);if(e.Lang.isString(g)){if(s)u=t.byId(g);else{u=e.Selector.query(g);switch(u.length){case 0:u=null;break;case 1:u=u[0];break;default:return n[2]=u,d._attach(n,r)}}if(!u)return p=d.onAvailable(g,function(){p.handle=d._attach(n,r)},d,!0,!1,s),p;g=u}return g?(e.Node&&e.instanceOf(g,e.Node)&&(g=e.Node.getDOMNode(g)),a=d._createWrapper(g,v,b,s,y),w&&e.mix(a.overrides,w),g==i&&v=="load"&&YUI.Env.windowLoaded&&(h=!0),s&&n.pop(),f=n[3],p=a._on(m,f,n.length>4?n.slice(4):null),h&&a.fire(),p):!1},detach:function(n,r,i,s){var o=e.Array(arguments,0,!0),u,a,f,h,p,m;o[o.length-1]===l&&(u=!0);if(n&&n.detach)return n.detach();typeof i=="string"&&(u?i=t.byId(i):(i=e.Selector.query(i),a=i.length,a<1?i=null:a==1&&(i=i[0])));if(!i)return!1;if(i.detach)return o.splice(2,1),i.detach.apply(i,o);if(c(i)){f=!0;for(h=0,a=i.length;h<a;++h)o[2]=i[h],f=e.Event.detach.apply(e.Event,o)&&f;return f}return!n||!r||!r.call?d.purgeElement(i,!1,n):(p="event:"+e.stamp(i)+n,m=v[p],m?m.detach(r):!1)},getEvent:function(t,n,r){var s=t||i.event;return r?s:new e.DOMEventFacade(s,n,v["event:"+e.stamp(n)+t.type])},generateId:function(e){return t.generateID(e)},_isValidCollection:c,_load:function(t){r||(r=!0,e.fire&&e.fire(f),d._poll())},_poll:function(){if(d.locked)return;if(e.UA.ie&&!YUI.Env.DOMReady){d.startInterval();return}d.locked=!0;var n,i,s,o,a,f,l=!r;l||(l=u>0),a=[],f=function(t,n){var r,i=n.override;try{n.compat?(n.override?i===!0?r=n.obj:r=i:r=t,n.fn.call(r,n.obj)):(r=n.obj||e.one(t),n.fn.apply(r,e.Lang.isArray(i)?i:[]))}catch(s){}};for(n=0,i=h.length;n<i;++n)s=h[n],s&&!s.checkReady&&(o=s.compat?t.byId(s.id):e.Selector.query(s.id,null,!0),o?(f(o,s),h[n]=null):a.push(s));for(n=0,i=h.length;n<i;++n){s=h[n];if(s&&s.checkReady){o=s.compat?t.byId(s.id):e.Selector.query(s.id,null,!0);if(o){if(r||o.get&&o.get("nextSibling")||o.nextSibling)f(o,s),h[n]=null}else a.push(s)}}u=a.length===0?0:u-1,l?d.startInterval():(clearInterval(d._interval),d._interval=null),d.locked=!1;return},purgeElement:function(t,n,r){var i=e.Lang.isString(t)?e.Selector.query(t,null,!0):t,s=d.getListeners(i,r),o,u,a,f;if(n&&i){s=s||[],a=e.Selector.query("*",i),u=a.length;for(o=0;o<u;++o)f=d.getListeners(a[o],r),f&&(s=s.concat(f))}if(s)for(o=0,u=s.length;o<u;++o)s[o].detachAll()},_clean:function(t){var n=t.key,r=t.domkey;o(t.el,t.type,t.fn,t.capture),delete v[n],delete e._yuievt.events[n],g[r]&&(delete g[r][n],e.Object.size(g[r])||delete g[r])},getListeners:function(t,r){var i=e.stamp(t,!0),s=g[i],o=[],u=r?"event:"+i+r:null,a=n.plugins;return s?(u?(a[r]&&a[r].eventDef&&(u+="_synth"),s[u]&&o.push(s[u]),u+="native",s[u]&&o.push(s[u])):e.each(s,function(e,t){o.push(e)}),o.length?o:null):null},_unload:function(t){e.each(v,function(e,n){e.type=="unload"&&e.fire(t),e.detachAll()}),o(i,"unload",a)},nativeAdd:s,nativeRemove:o}}();e.Event=d,r.injected||YUI.Env.windowLoaded?u():s(i,"load",u),e.UA.ie&&e.on(f,d._poll);try{s(i,"unload",a)}catch(v){}d.Custom=e.CustomEvent,d.Subscriber=e.Subscriber,d.Target=e.EventTarget,d.Handle=e.EventHandle,d.Facade=e.EventFacade,d._poll()}(),e.Env.evt.plugins.available={on:function(t,n,r,i){var s=arguments.length>4?e.Array(arguments,4,!0):null;return e.Event.onAvailable.call(e.Event,r,n,i,s)}},e.Env.evt.plugins.contentready={on:function(t,n,r,i){var s=arguments.length>4?e.Array(arguments,4,!0):null;return e.Event.onContentReady.call(e.Event,r,n,i,s)}}},"3.7.3",{requires:["event-custom-base"]});
diff --git a/js/yui3/event-contextmenu/event-contextmenu-min.js b/js/yui3/event-contextmenu/event-contextmenu-min.js
new file mode 100644
index 000000000..3df2ffc24
--- /dev/null
+++ b/js/yui3/event-contextmenu/event-contextmenu-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-contextmenu",function(e,t){var n=e.Event,r=e.DOM,i=e.UA,s=e.UA.os,o=i.ie,u=i.gecko,a=i.webkit,f=i.opera,l=s==="windows",c=s==="macintosh",h={},p={on:function(t,i,s,p){var d=[];d.push(n._attach(["contextmenu",function(n){n.preventDefault();var r=e.stamp(t),i=h[r];i&&(n.clientX=i.clientX,n.clientY=i.clientY,n.pageX=i.pageX,n.pageY=i.pageY,delete h[r]),s.fire(n)},t])),d.push(t[p?"delegate":"on"]("keydown",function(n){var i=this.getDOMNode(),p=n.shiftKey,d=n.keyCode,v=p&&d==121,m=l&&d==93,g=n.ctrlKey,y=d===77,b=c&&(a||u)&&g&&p&&n.altKey&&y,w=c&&f&&g&&p&&y,E=0,S=0,x,T,N,C,k,L,A;if(l&&(v||m)||b||w){((o||l&&(u||f))&&v||w)&&n.preventDefault(),k=r.getXY(i),L=k[0],A=k[1],x=r.docScrollX(),T=r.docScrollY(),e.Lang.isUndefined(L)||(E=L+i.offsetWidth/2-x,S=A+i.offsetHeight/2-T),N=E+x,C=S+T;if(m||l&&a&&v)h[e.stamp(t)]={clientX:E,clientY:S,pageX:N,pageY:C};if((o||l&&(u||f))&&v||c)n.clientX=E,n.clientY=S,n.pageX=N,n.pageY=C,s.fire(n)}},p)),i._handles=d},detach:function(t,n,r){e.each(n._handles,function(e){e.detach()})}};p.delegate=p.on,p.detachDelegate=p.detach,n.define("contextmenu",p,!0)},"3.7.3",{requires:["event-synthetic","dom-screen"]});
diff --git a/js/yui3/event-custom-base/event-custom-base-min.js b/js/yui3/event-custom-base/event-custom-base-min.js
new file mode 100644
index 000000000..b45185f85
--- /dev/null
+++ b/js/yui3/event-custom-base/event-custom-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-custom-base",function(e,t){e.Env.evt={handles:{},plugins:{}};var n=0,r=1,i={objs:null,before:function(t,r,i,s){var o=t,u;return s&&(u=[t,s].concat(e.Array(arguments,4,!0)),o=e.rbind.apply(e,u)),this._inject(n,o,r,i)},after:function(t,n,i,s){var o=t,u;return s&&(u=[t,s].concat(e.Array(arguments,4,!0)),o=e.rbind.apply(e,u)),this._inject(r,o,n,i)},_inject:function(t,n,r,i){var s=e.stamp(r),o,u;return r._yuiaop||(r._yuiaop={}),o=r._yuiaop,o[i]||(o[i]=new e.Do.Method(r,i),r[i]=function(){return o[i].exec.apply(o[i],arguments)}),u=s+e.stamp(n)+i,o[i].register(u,n,t),new e.EventHandle(o[i],u)},detach:function(e){e.detach&&e.detach()},_unload:function(e,t){}};e.Do=i,i.Method=function(e,t){this.obj=e,this.methodName=t,this.method=e[t],this.before={},this.after={}},i.Method.prototype.register=function(e,t,n){n?this.after[e]=t:this.before[e]=t},i.Method.prototype._delete=function(e){delete this.before[e],delete this.after[e]},i.Method.prototype.exec=function(){var t=e.Array(arguments,0,!0),n,r,s,o=this.before,u=this.after,a=!1;for(n in o)if(o.hasOwnProperty(n)){r=o[n].apply(this.obj,t);if(r)switch(r.constructor){case i.Halt:return r.retVal;case i.AlterArgs:t=r.newArgs;break;case i.Prevent:a=!0;break;default:}}a||(r=this.method.apply(this.obj,t)),i.originalRetVal=r,i.currentRetVal=r;for(n in u)if(u.hasOwnProperty(n)){s=u[n].apply(this.obj,t);if(s&&s.constructor==i.Halt)return s.retVal;s&&s.constructor==i.AlterReturn&&(r=s.newRetVal,i.currentRetVal=r)}return r},i.AlterArgs=function(e,t){this.msg=e,this.newArgs=t},i.AlterReturn=function(e,t){this.msg=e,this.newRetVal=t},i.Halt=function(e,t){this.msg=e,this.retVal=t},i.Prevent=function(e){this.msg=e},i.Error=i.Halt;var s=e.Array,o="after",u=["broadcast","monitored","bubbles","context","contextFn","currentTarget","defaultFn","defaultTargetOnly","details","emitFacade","fireOnce","async","host","preventable","preventedFn","queuable","silent","stoppedFn","target","type"],a=s.hash(u),f=Array.prototype.slice,l=9,c="yui:log",h=function(e,t,n){var r;for(r in t)a[r]&&(n||!(r in e))&&(e[r]=t[r]);return e};e.CustomEvent=function(t,n){this._kds=e.CustomEvent.keepDeprecatedSubs,n=n||{},this.id=e.stamp(this),this.type=t,this.context=e,this.logSystem=t==c,this.silent=this.logSystem,this._kds&&(this.subscribers={}),this._subscribers=[],this._kds&&(this.afters={}),this._afters=[],this.preventable=!0,this.bubbles=!0,this.signature=l,this.applyConfig(n,!0)},e.CustomEvent.keepDeprecatedSubs=!1,e.CustomEvent.mixConfigs=h,e.CustomEvent.prototype={constructor:e.CustomEvent,hasSubs:function(e){var t=this._subscribers.length,n=this._afters.length,r=this.sibling;return r&&(t+=r._subscribers.length,n+=r._afters.length),e?e=="after"?n:t:t+n},monitor:function(e){this.monitored=!0;var t=this.id+"|"+this.type+"_"+e,n=f.call(arguments,0);return n[0]=t,this.host.on.apply(this.host,n)},getSubs:function(){var e=this._subscribers,t=this._afters,n=this.sibling;return e=n?e.concat(n._subscribers):e.concat(),t=n?t.concat(n._afters):t.concat(),[e,t]},applyConfig:function(e,t){h(this,e,t)},_on:function(t,n,r,i){var s=new e.Subscriber(t,n,r,i);return this.fireOnce&&this.fired&&(this.async?setTimeout(e.bind(this._notify,this,s,this.firedWith),0):this._notify(s,this.firedWith)),i==o?this._afters.push(s):this._subscribers.push(s),this._kds&&(i==o?this.afters[s.id]=s:this.subscribers[s.id]=s),new e.EventHandle(this,s)},subscribe:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this._on(e,t,n,!0)},on:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this.monitored&&this.host&&this.host._monitor("attach",this,{args:arguments}),this._on(e,t,n,!0)},after:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this._on(e,t,n,o)},detach:function(e,t){if(e&&e.detach)return e.detach();var n,r,i=0,s=this._subscribers,o=this._afters;for(n=s.length;n>=0;n--)r=s[n],r&&(!e||e===r.fn)&&(this._delete(r,s,n),i++);for(n=o.length;n>=0;n--)r=o[n],r&&(!e||e===r.fn)&&(this._delete(r,o,n),i++);return i},unsubscribe:function(){return this.detach.apply(this,arguments)},_notify:function(e,t,n){var r;return r=e.notify(t,this),!1===r||this.stopped>1?!1:!0},log:function(e,t){},fire:function(){if(this.fireOnce&&this.fired)return!0;var e=f.call(arguments,0);return this.fired=!0,this.fireOnce&&(this.firedWith=e),this.emitFacade?this.fireComplex(e):this.fireSimple(e)},fireSimple:function(e){this.stopped=0,this.prevented=0;if(this.hasSubs()){var t=this.getSubs();this._procSubs(t[0],e),this._procSubs(t[1],e)}return this._broadcast(e),this.stopped?!1:!0},fireComplex:function(e){return e[0]=e[0]||{},this.fireSimple(e)},_procSubs:function(e,t,n){var r,i,s;for(i=0,s=e.length;i<s;i++){r=e[i];if(r&&r.fn){!1===this._notify(r,t,n)&&(this.stopped=2);if(this.stopped==2)return!1}}return!0},_broadcast:function(t){if(!this.stopped&&this.broadcast){var n=t.concat();n.unshift(this.type),this.host!==e&&e.fire.apply(e,n),this.broadcast==2&&e.Global.fire.apply(e.Global,n)}},unsubscribeAll:function(){return this.detachAll.apply(this,arguments)},detachAll:function(){return this.detach()},_delete:function(e,t,n){var r=e._when;t||(t=r===o?this._afters:this._subscribers,n=s.indexOf(t,e,0)),e&&t[n]===e&&t.splice(n,1),this._kds&&(r===o?delete this.afters[e.id]:delete this.subscribers[e.id]),this.monitored&&this.host&&this.host._monitor("detach",this,{ce:this,sub:e}),e&&(e.deleted=!0)}},e.Subscriber=function(t,n,r,i){this.fn=t,this.context=n,this.id=e.stamp(this),this.args=r,this._when=i},e.Subscriber.prototype={constructor:e.Subscriber,_notify:function(e,t,n){if(this.deleted&&!this.postponed){if(!this.postponed)return delete this.postponed,null;delete this.fn,delete this.context}var r=this.args,i;switch(n.signature){case 0:i=this.fn.call(e,n.type,t,e);break;case 1:i=this.fn.call(e,t[0]||null,e);break;default:r||t?(t=t||[],r=r?t.concat(r):t,i=this.fn.apply(e,r)):i=this.fn.call(e)}return this.once&&n._delete(this),i},notify:function(t,n){var r=this.context,i=!0;r||(r=n.contextFn?n.contextFn():n.context);if(e.config&&e.config.throwFail)i=this._notify(r,t,n);else try{i=this._notify(r,t,n)}catch(s){e.error(this+" failed: "+s.message,s)}return i},contains:function(e,t){return t?this.fn==e&&this.context==t:this.fn==e},valueOf:function(){return this.id}},e.EventHandle=function(e,t){this.evt=e,this.sub=t},e.EventHandle.prototype={batch:function(t,n){t.call(n||this,this),e.Lang.isArray(this.evt)&&e.Array.each(this.evt,function(e){e.batch.call(n||e,t)})},detach:function(){var t=this.evt,n=0,r;if(t)if(e.Lang.isArray(t))for(r=0;r<t.length;r++)n+=t[r].detach();else t._delete(this.sub),n=1;return n},monitor:function(e){return this.evt.monitor.apply(this.evt,arguments)}};var p=e.Lang,d=":",v="|",m="~AFTER~",g=/(.*?)(:)(.*?)/,y=e.cached(function(e){return e.replace(g,"*$2$3")}),b=e.cached(function(e,t){return!t||typeof e!="string"||e.indexOf(d)>-1?e:t+d+e}),w=e.cached(function(e,t){var n=e,r,i,s;return p.isString(n)?(s=n.indexOf(m),s>-1&&(i=!0,n=n.substr(m.length)),s=n.indexOf(v),s>-1&&(r=n.substr(0,s),n=n.substr(s+1),n=="*"&&(n=null)),[r,t?b(n,t):n,i,n]):n}),E=function(t){var n=p.isObject(t)?t:{};this._yuievt=this._yuievt||{id:e.guid(),events:{},targets:{},config:n,chain:"chain"in n?n.chain:e.config.chain,bubbling:!1,defaults:{context:n.context||this,host:this,emitFacade:n.emitFacade,fireOnce:n.fireOnce,queuable:n.queuable,monitored:n.monitored,broadcast:n.broadcast,defaultTargetOnly:n.defaultTargetOnly,bubbles:"bubbles"in n?n.bubbles:!0}}};E.prototype={constructor:E,once:function(){var e=this.on.apply(this,arguments);return e.batch(function(e){e.sub&&(e.sub.once=!0)}),e},onceAfter:function(){var e=this.after.apply(this,arguments);return e.batch(function(e){e.sub&&(e.sub.once=!0)}),e},parseType:function(e,t){return w(e,t||this._yuievt.config.prefix)},on:function(t,n,r){var i=this._yuievt,s=w(t,i.config.prefix),o,u,a,l,c,h,d,v=e.Env.evt.handles,g,y,b,E=e.Node,S,x,T;this._monitor("attach",s[1],{args:arguments,category:s[0],after:s[2]});if(p.isObject(t))return p.isFunction(t)?e.Do.before.apply(e.Do,arguments):(o=n,u=r,a=f.call(arguments,0),l=[],p.isArray(t)&&(T=!0),g=t._after,delete t._after,e.each(t,function(e,t){p.isObject(e)&&(o=e.fn||(p.isFunction(e)?e:o),u=e.context||u);var n=g?m:"";a[0]=n+(T?e:t),a[1]=o,a[2]=u,l.push(this.on.apply(this,a))},this),i.chain?this:new e.EventHandle(l));h=s[0],g=s[2],b=s[3];if(E&&e.instanceOf(this,E)&&b in E.DOM_EVENTS)return a=f.call(arguments,0),a.splice(2,0,E.getDOMNode(this)),e.on.apply(e,a);t=s[1];if(e.instanceOf(this,YUI)){y=e.Env.evt.plugins[t],a=f.call(arguments,0),a[0]=b,E&&(S=a[2],e.instanceOf(S,e.NodeList)?S=e.NodeList.getDOMNodes(S):e.instanceOf(S,E)&&(S=E.getDOMNode(S)),x=b in E.DOM_EVENTS,x&&(a[2]=S));if(y)d=y.on.apply(e,a);else if(!t||x)d=e.Event._attach(a)}return d||(c=i.events[t]||this.publish(t),d=c._on(n,r,arguments.length>3?f.call(arguments,3):null,g?"after":!0)),h&&(v[h]=v[h]||{},v[h][t]=v[h][t]||[],v[h][t].push(d)),i.chain?this:d},subscribe:function(){return this.on.apply(this,arguments)},detach:function(t,n,r){var i=this._yuievt.events,s,o=e.Node,u=o&&e.instanceOf(this,o);if(!t&&this!==e){for(s in i)i.hasOwnProperty(s)&&i[s].detach(n,r);return u&&e.Event.purgeElement(o.getDOMNode(this)),this}var a=w(t,this._yuievt.config.prefix),l=p.isArray(a)?a[0]:null,c=a?a[3]:null,h,d=e.Env.evt.handles,v,m,g,y,b=function(e,t,n){var r=e[t],i,s;if(r)for(s=r.length-1;s>=0;--s)i=r[s].evt,(i.host===n||i.el===n)&&r[s].detach()};if(l){m=d[l],t=a[1],v=u?e.Node.getDOMNode(this):this;if(m){if(t)b(m,t,v);else for(s in m)m.hasOwnProperty(s)&&b(m,s,v);return this}}else{if(p.isObject(t)&&t.detach)return t.detach(),this;if(u&&(!c||c in o.DOM_EVENTS))return g=f.call(arguments,0),g[2]=o.getDOMNode(this),e.detach.apply(e,g),this}h=e.Env.evt.plugins[c];if(e.instanceOf(this,YUI)){g=f.call(arguments,0);if(h&&h.detach)return h.detach.apply(e,g),this;if(!t||!h&&o&&t in o.DOM_EVENTS)return g[0]=t,e.Event.detach.apply(e.Event,g),this}return y=i[a[1]],y&&y.detach(n,r),this},unsubscribe:function(){return this.detach.apply(this,arguments)},detachAll:function(e){return this.detach(e)},unsubscribeAll:function(){return this.detachAll.apply(this,arguments)},publish:function(t,n){var r,i,s,o,u=this._yuievt,a=u.config.prefix;return p.isObject(t)?(s={},e.each(t,function(e,t){s[t]=this.publish(t,e||n)},this),s):(t=a?b(t,a):t,r=u.events,i=r[t],this._monitor("publish",t,{args:arguments}),i?n&&i.applyConfig(n,!0):(o=u.defaults,i=new e.CustomEvent(t,o),n&&i.applyConfig(n,!0),r[t]=i),r[t])},_monitor:function(e,t,n){var r,i,s;if(t){typeof t=="string"?(s=t,i=this.getEvent(t,!0)):(i=t,s=t.type);if(this._yuievt.config.monitored&&(!i||i.monitored)||i&&i.monitored)r=s+"_"+e,n.monitored=e,this.fire.call(this,r,n)}},fire:function(e){var t=p.isString(e),n=t?e:e&&e.type,r=this._yuievt,i=r.config.prefix,s,o,u,a=t?f.call(arguments,1):arguments;n=i?b(n,i):n,s=this.getEvent(n,!0),u=this.getSibling(n,s),u&&!s&&(s=this.publish(n)),this._monitor("fire",s||n,{args:a});if(!s){if(r.hasTargets)return this.bubble({type:n},a,this);o=!0}else s.sibling=u,o=s.fire.apply(s,a);return r.chain?this:o},getSibling:function(e,t){var n;return e.indexOf(d)>-1&&(e=y(e),n=this.getEvent(e,!0),n&&(n.applyConfig(t),n.bubbles=!1,n.broadcast=0)),n},getEvent:function(e,t){var n,r;return t||(n=this._yuievt.config.prefix,e=n?b(e,n):e),r=this._yuievt.events,r[e]||null},after:function(t,n){var r=f.call(arguments,0);switch(p.type(t)){case"function":return e.Do.after.apply(e.Do,arguments);case"array":case"object":r[0]._after=!0;break;default:r[0]=m+t}return this.on.apply(this,r)},before:function(){return this.on.apply(this,arguments)}},e.EventTarget=E,e.mix(e,E.prototype),E.call(e,{bubbles:!1}),YUI.Env.globalEvents=YUI.Env.globalEvents||new E,e.Global=YUI.Env.globalEvents},"3.7.3",{requires:["oop"]});
diff --git a/js/yui3/event-custom-complex/event-custom-complex-min.js b/js/yui3/event-custom-complex/event-custom-complex-min.js
new file mode 100644
index 000000000..378714fc8
--- /dev/null
+++ b/js/yui3/event-custom-complex/event-custom-complex-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-custom-complex",function(e,t){var n,r,i,s={},o=e.CustomEvent.prototype,u=e.EventTarget.prototype,a=function(e,t){var n;for(n in t)r.hasOwnProperty(n)||(e[n]=t[n])};e.EventFacade=function(e,t){e=e||s,this._event=e,this.details=e.details,this.type=e.type,this._type=e.type,this.target=e.target,this.currentTarget=t,this.relatedTarget=e.relatedTarget},e.mix(e.EventFacade.prototype,{stopPropagation:function(){this._event.stopPropagation(),this.stopped=1},stopImmediatePropagation:function(){this._event.stopImmediatePropagation(),this.stopped=2},preventDefault:function(){this._event.preventDefault(),this.prevented=1},halt:function(e){this._event.halt(e),this.prevented=1,this.stopped=e?2:1}}),o.fireComplex=function(t){var n,r,i,s,o,u,a,f,l,c=this,h=c.host||c,p,d;if(c.stack&&c.queuable&&c.type!=c.stack.next.type)return c.stack.queue.push([c,t]),!0;n=c.stack||{id:c.id,next:c,silent:c.silent,stopped:0,prevented:0,bubbling:null,type:c.type,afterQueue:new e.Queue,defaultTargetOnly:c.defaultTargetOnly,queue:[]},f=c.getSubs(),c.stopped=c.type!==n.type?0:n.stopped,c.prevented=c.type!==n.type?0:n.prevented,c.target=c.target||h,c.stoppedFn&&(a=new e.EventTarget({fireOnce:!0,context:h}),c.events=a,a.on("stopped",c.stoppedFn)),c.currentTarget=h,c.details=t.slice(),c._facade=null,r=c._getFacade(t),e.Lang.isObject(t[0])?t[0]=r:t.unshift(r),f[0]&&c._procSubs(f[0],t,r),c.bubbles&&h.bubble&&!c.stopped&&(d=n.bubbling,n.bubbling=c.type,n.type!=c.type&&(n.stopped=0,n.prevented=0),u=h.bubble(c,t,null,n),c.stopped=Math.max(c.stopped,n.stopped),c.prevented=Math.max(c.prevented,n.prevented),n.bubbling=d),c.prevented?c.preventedFn&&c.preventedFn.apply(h,t):c.defaultFn&&(!c.defaultTargetOnly&&!n.defaultTargetOnly||h===r.target)&&c.defaultFn.apply(h,t),c._broadcast(t);if(f[1]&&!c.prevented&&c.stopped<2)if(n.id===c.id||c.type!=h._yuievt.bubbling){c._procSubs(f[1],t,r);while(p=n.afterQueue.last())p()}else l=f[1],n.execDefaultCnt&&(l=e.merge(l),e.each(l,function(e){e.postponed=!0})),n.afterQueue.add(function(){c._procSubs(l,t,r)});c.target=null;if(n.id===c.id){s=n.queue;while(s.length)i=s.pop(),o=i[0],n.next=o,o.fire.apply(o,i[1]);c.stack=null}return u=!c.stopped,c.type!=h._yuievt.bubbling&&(n.stopped=0,n.prevented=0,c.stopped=0,c.prevented=0),c._facade=null,u},o._getFacade=function(){var t=this._facade,n,r=this.details;return t||(t=new e.EventFacade(this,this.currentTarget)),n=r&&r[0],e.Lang.isObject(n,!0)&&(a(t,n),t.type=n.type||t.type),t.details=this.details,t.target=this.originalTarget||this.target,t.currentTarget=this.currentTarget,t.stopped=0,t.prevented=0,this._facade=t,this._facade},o.stopPropagation=function(){this.stopped=1,this.stack&&(this.stack.stopped=1),this.events&&this.events.fire("stopped",this)},o.stopImmediatePropagation=function(){this.stopped=2,this.stack&&(this.stack.stopped=2),this.events&&this.events.fire("stopped",this)},o.preventDefault=function(){this.preventable&&(this.prevented=1,this.stack&&(this.stack.prevented=1))},o.halt=function(e){e?this.stopImmediatePropagation():this.stopPropagation(),this.preventDefault()},u.addTarget=function(t){this._yuievt.targets[e.stamp(t)]=t,this._yuievt.hasTargets=!0},u.getTargets=function(){return e.Object.values(this._yuievt.targets)},u.removeTarget=function(t){delete this._yuievt.targets[e.stamp(t)]},u.bubble=function(e,t,n,r){var i=this._yuievt.targets,s=!0,o,u=e&&e.type,a,f,l,c,h=n||e&&e.target||this,p;if(!e||!e.stopped&&i)for(f in i)if(i.hasOwnProperty(f)){o=i[f],a=o.getEvent(u,!0),c=o.getSibling(u,a),c&&!a&&(a=o.publish(u)),p=o._yuievt.bubbling,o._yuievt.bubbling=u;if(!a)o._yuievt.hasTargets&&o.bubble(e,t,h,r);else{a.sibling=c,a.target=h,a.originalTarget=h,a.currentTarget=o,l=a.broadcast,a.broadcast=!1,a.emitFacade=!0,a.stack=r,s=s&&a.fire.apply(a,t||e.details||[]),a.broadcast=l,a.originalTarget=null;if(a.stopped)break}o._yuievt.bubbling=p}return s},n=new e.EventFacade,r={};for(i in n)r[i]=!0},"3.7.3",{requires:["event-custom-base"]});
diff --git a/js/yui3/event-delegate/event-delegate-min.js b/js/yui3/event-delegate/event-delegate-min.js
new file mode 100644
index 000000000..aad5483a5
--- /dev/null
+++ b/js/yui3/event-delegate/event-delegate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-delegate",function(e,t){function f(t,r,u,l){var c=n(arguments,0,!0),h=i(u)?u:null,p,d,v,m,g,y,b,w,E;if(s(t)){w=[];if(o(t))for(y=0,b=t.length;y<b;++y)c[0]=t[y],w.push(e.delegate.apply(e,c));else{c.unshift(null);for(y in t)t.hasOwnProperty(y)&&(c[0]=y,c[1]=t[y],w.push(e.delegate.apply(e,c)))}return new e.EventHandle(w)}p=t.split(/\|/),p.length>1&&(g=p.shift(),c[0]=t=p.shift()),d=e.Node.DOM_EVENTS[t],s(d)&&d.delegate&&(E=d.delegate.apply(d,arguments));if(!E){if(!t||!r||!u||!l)return;v=h?e.Selector.query(h,null,!0):u,!v&&i(u)&&(E=e.on("available",function(){e.mix(E,e.delegate.apply(e,c),!0)},u)),!E&&v&&(c.splice(2,2,v),E=e.Event._attach(c,{facade:!1}),E.sub.filter=l,E.sub._notify=f.notifySub)}return E&&g&&(m=a[g]||(a[g]={}),m=m[t]||(m[t]=[]),m.push(E)),E}var n=e.Array,r=e.Lang,i=r.isString,s=r.isObject,o=r.isArray,u=e.Selector.test,a=e.Env.evt.handles;f.notifySub=function(t,r,i){r=r.slice(),this.args&&r.push.apply(r,this.args);var s=f._applyFilter(this.filter,r,i),o,u,a,l;if(s){s=n(s),o=r[0]=new e.DOMEventFacade(r[0],i.el,i),o.container=e.one(i.el);for(u=0,a=s.length;u<a&&!o.stopped;++u){o.currentTarget=e.one(s[u]),l=this.fn.apply(this.context||o.currentTarget,r);if(l===!1)break}return l}},f.compileFilter=e.cached(function(e){return function(t,n){return u(t._node,e,n.currentTarget===n.target?null:n.currentTarget._node)}}),f._applyFilter=function(t,n,r){var s=n[0],o=r.el,a=s.target||s.srcElement,f=[],l=!1;a.nodeType===3&&(a=a.parentNode),n.unshift(a);if(i(t))while(a){l=a===o,u(a,t,l?null:o)&&f.push(a);if(l)break;a=a.parentNode}else{n[0]=e.one(a),n[1]=new e.DOMEventFacade(s,o,r);while(a){t.apply(n[0],n)&&f.push(a);if(a===o)break;a=a.parentNode,n[0]=e.one(a)}n[1]=s}return f.length<=1&&(f=f[0]),n.shift(),f},e.delegate=e.Event.delegate=f},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/event-flick/event-flick-min.js b/js/yui3/event-flick/event-flick-min.js
new file mode 100644
index 000000000..16c75be1c
--- /dev/null
+++ b/js/yui3/event-flick/event-flick-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-flick",function(e,t){var n=e.Event._GESTURE_MAP,r={start:n.start,end:n.end,move:n.move},i="start",s="end",o="move",u="ownerDocument",a="minVelocity",f="minDistance",l="preventDefault",c="_fs",h="_fsh",p="_feh",d="_fmh",v="nodeType";e.Event.define("flick",{on:function(e,t,n){var s=e.on(r[i],this._onStart,this,e,t,n);t[h]=s},detach:function(e,t,n){var r=t[h],i=t[p];r&&(r.detach(),t[h]=null),i&&(i.detach(),t[p]=null)},processArgs:function(t){var n=t.length>3?e.merge(t.splice(3,1)[0]):{};return a in n||(n[a]=this.MIN_VELOCITY),f in n||(n[f]=this.MIN_DISTANCE),l in n||(n[l]=this.PREVENT_DEFAULT),n},_onStart:function(t,n,i,a){var f=!0,l,h,m,g=i._extra.preventDefault,y=t;t.touches&&(f=t.touches.length===1,t=t.touches[0]),f&&(g&&(!g.call||g(t))&&y.preventDefault(),t.flick={time:(new Date).getTime()},i[c]=t,l=i[p],m=n.get(v)===9?n:n.get(u),l||(l=m.on(r[s],e.bind(this._onEnd,this),null,n,i,a),i[p]=l),i[d]=m.once(r[o],e.bind(this._onMove,this),null,n,i,a))},_onMove:function(e,t,n,r){var i=n[c];i&&i.flick&&(i.flick.time=(new Date).getTime())},_onEnd:function(e,t,n,r){var i=(new Date).getTime(),s=n[c],o=!!s,u=e,h,p,v,m,g,y,b,w,E=n[d];E&&(E.detach(),delete n[d]),o&&(e.changedTouches&&(e.changedTouches.length===1&&e.touches.length===0?u=e.changedTouches[0]:o=!1),o&&(m=n._extra,v=m[l],v&&(!v.call||v(e))&&e.preventDefault(),h=s.flick.time,i=(new Date).getTime(),p=i-h,g=[u.pageX-s.pageX,u.pageY-s.pageY],m.axis?w=m.axis:w=Math.abs(g[0])>=Math.abs(g[1])?"x":"y",y=g[w==="x"?0:1],b=p!==0?y/p:0,isFinite(b)&&Math.abs(y)>=m[f]&&Math.abs(b)>=m[a]&&(e.type="flick",e.flick={time:p,distance:y,velocity:b,axis:w,start:s},r.fire(e)),n[c]=null))},MIN_VELOCITY:0,MIN_DISTANCE:0,PREVENT_DEFAULT:!1})},"3.7.3",{requires:["node-base","event-touch","event-synthetic"]});
diff --git a/js/yui3/event-focus/event-focus-min.js b/js/yui3/event-focus/event-focus-min.js
new file mode 100644
index 000000000..2df52f2e2
--- /dev/null
+++ b/js/yui3/event-focus/event-focus-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-focus",function(e,t){function u(t,r,u){var a="_"+t+"Notifiers";e.Event.define(t,{_useActivate:o,_attach:function(i,s,o){return e.DOM.isWindow(i)?n._attach([t,function(e){s.fire(e)},i]):n._attach([r,this._proxy,i,this,s,o],{capture:!0})},_proxy:function(t,r,i){var s=t.target,f=t.currentTarget,l=s.getData(a),c=e.stamp(f._node),h=o||s!==f,p;r.currentTarget=i?s:f,r.container=i?f:null,l?h=!0:(l={},s.setData(a,l),h&&(p=n._attach([u,this._notify,s._node]).sub,p.once=!0)),l[c]||(l[c]=[]),l[c].push(r),h||this._notify(t)},_notify:function(t,n){var r=t.currentTarget,i=r.getData(a),o=r.ancestors(),u=r.get("ownerDocument"),f=[],l=i?e.Object.keys(i).length:0,c,h,p,d,v,m,g,y,b,w;r.clearData(a),o.push(r),u&&o.unshift(u),o._nodes.reverse(),l&&(m=l,o.some(function(t){var n=e.stamp(t),r=i[n],s,o;if(r){l--;for(s=0,o=r.length;s<o;++s)r[s].handle.sub.filter&&f.push(r[s])}return!l}),l=m);while(l&&(c=o.shift())){d=e.stamp(c),h=i[d];if(h){for(g=0,y=h.length;g<y;++g){p=h[g],b=p.handle.sub,v=!0,t.currentTarget=c,b.filter&&(v=b.filter.apply(c,[c,t].concat(b.args||[])),f.splice(s(f,p),1)),v&&(t.container=p.container,w=p.fire(t));if(w===!1||t.stopped===2)break}delete h[d],l--}if(t.stopped!==2)for(g=0,y=f.length;g<y;++g){p=f[g],b=p.handle.sub,b.filter.apply(c,[c,t].concat(b.args||[]))&&(t.container=p.container,t.currentTarget=c,w=p.fire(t));if(w===!1||t.stopped===2)break}if(t.stopped)break}},on:function(e,t,n){t.handle=this._attach(e._node,n)},detach:function(e,t){t.handle.detach()},delegate:function(t,n,r,s){i(s)&&(n.filter=function(n){return e.Selector.test(n._node,s,t===n?null:t._node)}),n.handle=this._attach(t._node,r,!0)},detachDelegate:function(e,t){t.handle.detach()}},!0)}var n=e.Event,r=e.Lang,i=r.isString,s=e.Array.indexOf,o=function(){var t=e.config.doc.createElement("p"),n;return t.setAttribute("onbeforeactivate",";"),n=t.onbeforeactivate,n!==undefined}();o?(u("focus","beforeactivate","focusin"),u("blur","beforedeactivate","focusout")):(u("focus","focus","focus"),u("blur","blur","blur"))},"3.7.3",{requires:["event-synthetic"]});
diff --git a/js/yui3/event-hover/event-hover-min.js b/js/yui3/event-hover/event-hover-min.js
new file mode 100644
index 000000000..fe861718e
--- /dev/null
+++ b/js/yui3/event-hover/event-hover-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-hover",function(e,t){var n=e.Lang.isFunction,r=function(){},i={processArgs:function(e){var t=n(e[2])?2:3;return n(e[t])?e.splice(t,1)[0]:r},on:function(e,t,n,r){var i=t.args?t.args.slice():[];i.unshift(null),t._detach=e[r?"delegate":"on"]({mouseenter:function(e){e.phase="over",n.fire(e)},mouseleave:function(e){var n=t.context||this;i[0]=e,e.type="hover",e.phase="out",t._extra.apply(n,i)}},r)},detach:function(e,t,n){t._detach.detach()}};i.delegate=i.on,i.detachDelegate=i.detach,e.Event.define("hover",i)},"3.7.3",{requires:["event-mouseenter"]});
diff --git a/js/yui3/event-key/event-key-min.js b/js/yui3/event-key/event-key-min.js
new file mode 100644
index 000000000..b53328765
--- /dev/null
+++ b/js/yui3/event-key/event-key-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-key",function(e,t){var n="+alt",r="+ctrl",i="+meta",s="+shift",o=e.Lang.trim,u={KEY_MAP:{enter:13,esc:27,backspace:8,tab:9,pageup:33,pagedown:34},_typeRE:/^(up|down|press):/,_keysRE:/^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,processArgs:function(t){var n=t.splice(3,1)[0],r=e.Array.hash(n.match(/\+(?:alt|ctrl|meta|shift)\b/g)||[]),i={type:this._typeRE.test(n)?RegExp.$1:null,mods:r,keys:null},s=n.replace(this._keysRE,""),u,a,f,l;if(s){s=s.split(","),i.keys={};for(l=s.length-1;l>=0;--l){u=o(s[l]);if(!u)continue;+u==u?i.keys[u]=r:(f=u.toLowerCase(),this.KEY_MAP[f]?(i.keys[this.KEY_MAP[f]]=r,i.type||(i.type="down")):(u=u.charAt(0),a=u.toUpperCase(),r["+shift"]&&(u=a),i.keys[u.charCodeAt(0)]=u===a?e.merge(r,{"+shift":!0}):r))}}return i.type||(i.type="press"),i},on:function(e,t,o,u){var a=t._extra,f="key"+a.type,l=a.keys,c=u?"delegate":"on";t._detach=e[c](f,function(e){var t=l?l[e.which]:a.mods;t&&(!t[n]||t[n]&&e.altKey)&&(!t[r]||t[r]&&e.ctrlKey)&&(!t[i]||t[i]&&e.metaKey)&&(!t[s]||t[s]&&e.shiftKey)&&o.fire(e)},u)},detach:function(e,t,n){t._detach.detach()}};u.delegate=u.on,u.detachDelegate=u.detach,e.Event.define("key",u,!0)},"3.7.3",{requires:["event-synthetic"]});
diff --git a/js/yui3/event-mouseenter/event-mouseenter-min.js b/js/yui3/event-mouseenter/event-mouseenter-min.js
new file mode 100644
index 000000000..d9b3341fc
--- /dev/null
+++ b/js/yui3/event-mouseenter/event-mouseenter-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-mouseenter",function(e,t){var n=e.Env.evt.dom_wrappers,r=e.DOM.contains,i=e.Array,s=function(){},o={proxyType:"mouseover",relProperty:"fromElement",_notify:function(t,i,s){var o=this._node,u=t.relatedTarget||t[i];o!==u&&!r(o,u)&&s.fire(new e.DOMEventFacade(t,o,n["event:"+e.stamp(o)+t.type]))},on:function(t,n,r){var i=e.Node.getDOMNode(t),s=[this.proxyType,this._notify,i,null,this.relProperty,r];n.handle=e.Event._attach(s,{facade:!1})},detach:function(e,t){t.handle.detach()},delegate:function(t,n,r,i){var o=e.Node.getDOMNode(t),u=[this.proxyType,s,o,null,r];n.handle=e.Event._attach(u,{facade:!1}),n.handle.sub.filter=i,n.handle.sub.relProperty=this.relProperty,n.handle.sub._notify=this._filterNotify},_filterNotify:function(t,n,s){n=n.slice(),this.args&&n.push.apply(n,this.args);var o=e.delegate._applyFilter(this.filter,n,s),u=n[0].relatedTarget||n[0][this.relProperty],a,f,l,c,h;if(o){o=i(o);for(f=0,l=o.length&&(!a||!a.stopped);f<l;++f){h=o[0];if(!r(h,u)){a||(a=new e.DOMEventFacade(n[0],h,s),a.container=e.one(s.el)),a.currentTarget=e.one(h),c=n[1].fire(a);if(c===!1)break}}}return c},detachDelegate:function(e,t){t.handle.detach()}};e.Event.define("mouseenter",o,!0),e.Event.define("mouseleave",e.merge(o,{proxyType:"mouseout",relProperty:"toElement"}),!0)},"3.7.3",{requires:["event-synthetic"]});
diff --git a/js/yui3/event-mousewheel/event-mousewheel-min.js b/js/yui3/event-mousewheel/event-mousewheel-min.js
new file mode 100644
index 000000000..8f8f6b5eb
--- /dev/null
+++ b/js/yui3/event-mousewheel/event-mousewheel-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-mousewheel",function(e,t){var n="DOMMouseScroll",r=function(t){var r=e.Array(t,0,!0),i;return e.UA.gecko?(r[0]=n,i=e.config.win):i=e.config.doc,r.length<3?r[2]=i:r.splice(2,0,i),r};e.Env.evt.plugins.mousewheel={on:function(){return e.Event._attach(r(arguments))},detach:function(){return e.Event.detach.apply(e.Event,r(arguments))}}},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/event-move/event-move-min.js b/js/yui3/event-move/event-move-min.js
new file mode 100644
index 000000000..09934d2c9
--- /dev/null
+++ b/js/yui3/event-move/event-move-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-move",function(e,t){var n=e.Event._GESTURE_MAP,r={start:n.start,end:n.end,move:n.move},i="start",s="move",o="end",u="gesture"+s,a=u+o,f=u+i,l="_msh",c="_mh",h="_meh",p="_dmsh",d="_dmh",v="_dmeh",m="_ms",g="_m",y="minTime",b="minDistance",w="preventDefault",E="button",S="ownerDocument",x="currentTarget",T="target",N="nodeType",C=e.config.win&&"msPointerEnabled"in e.config.win.navigator,k="msTouchActionCount",L="msInitTouchAction",A=function(t,n,r){var i=r?4:3,s=n.length>i?e.merge(n.splice(i,1)[0]):{};return w in s||(s[w]=t.PREVENT_DEFAULT),s},O=function(e,t){return t._extra.root||e.get(N)===9?e:e.get(S)},M=function(t){var n=t.getDOMNode();return t.compareTo(e.config.doc)&&n.documentElement?n.documentElement:!1},_=function(e,t,n){e.pageX=t.pageX,e.pageY=t.pageY,e.screenX=t.screenX,e.screenY=t.screenY,e.clientX=t.clientX,e.clientY=t.clientY,e[T]=e[T]||t[T],e[x]=e[x]||t[x],e[E]=n&&n[E]||1},D=function(t){var n=M(t)||t.getDOMNode(),r=t.getData(k);C&&(r||(r=0,t.setData(L,n.style.msTouchAction)),n.style.msTouchAction=e.Event._DEFAULT_TOUCH_ACTION,r++,t.setData(k,r))},P=function(e){var t=M(e)||e.getDOMNode(),n=e.getData(k),r=e.getData(L);C&&(n--,e.setData(k,n),n===0&&t.style.msTouchAction!==r&&(t.style.msTouchAction=r))},H=function(e,t){t&&(!t.call||t(e))&&e.preventDefault()},B=e.Event.define;e.Event._DEFAULT_TOUCH_ACTION="none",B(f,{on:function(e,t,n){D(e),t[l]=e.on(r[i],this._onStart,this,e,t,n)},delegate:function(e,t,n,s){var o=this;t[p]=e.delegate(r[i],function(r){o._onStart(r,e,t,n,!0)},s)},detachDelegate:function(e,t,n,r){var i=t[p];i&&(i.detach(),t[p]=null),P(e)},detach:function(e,t,n){var r=t[l];r&&(r.detach(),t[l]=null),P(e)},processArgs:function(e,t){var n=A(this,e,t);return y in n||(n[y]=this.MIN_TIME),b in n||(n[b]=this.MIN_DISTANCE),n},_onStart:function(t,n,i,u,a){a&&(n=t[x]);var f=i._extra,l=!0,c=f[y],h=f[b],p=f.button,d=f[w],v=O(n,i),m;t.touches?t.touches.length===1?_(t,t.touches[0],f):l=!1:l=p===undefined||p===t.button,l&&(H(t,d),c===0||h===0?this._start(t,n,u,f):(m=[t.pageX,t.pageY],c>0&&(f._ht=e.later(c,this,this._start,[t,n,u,f]),f._hme=v.on(r[o],e.bind(function(){this._cancel(f)},this))),h>0&&(f._hm=v.on(r[s],e.bind(function(e){(Math.abs(e.pageX-m[0])>h||Math.abs(e.pageY-m[1])>h)&&this._start(t,n,u,f)},this)))))},_cancel:function(e){e._ht&&(e._ht.cancel(),e._ht=null),e._hme&&(e._hme.detach(),e._hme=null),e._hm&&(e._hm.detach(),e._hm=null)},_start:function(e,t,n,r){r&&this._cancel(r),e.type=f,t.setData(m,e),n.fire(e)},MIN_TIME:0,MIN_DISTANCE:0,PREVENT_DEFAULT:!1}),B(u,{on:function(e,t,n){D(e);var i=O(e,t,r[s]),o=i.on(r[s],this._onMove,this,e,t,n);t[c]=o},delegate:function(e,t,n,i){var o=this;t[d]=e.delegate(r[s],function(r){o._onMove(r,e,t,n,!0)},i)},detach:function(e,t,n){var r=t[c];r&&(r.detach(),t[c]=null),P(e)},detachDelegate:function(e,t,n,r){var i=t[d];i&&(i.detach(),t[d]=null),P(e)},processArgs:function(e,t){return A(this,e,t)},_onMove:function(e,t,n,r,i){i&&(t=e[x]);var s=n._extra.standAlone||t.getData(m),o=n._extra.preventDefault;s&&(e.touches&&(e.touches.length===1?_(e,e.touches[0]):s=!1),s&&(H(e,o),e.type=u,r.fire(e)))},PREVENT_DEFAULT:!1}),B(a,{on:function(e,t,n){D(e);var i=O(e,t),s=i.on(r[o],this._onEnd,this,e,t,n);t[h]=s},delegate:function(e,t,n,i){var s=this;t[v]=e.delegate(r[o],function(r){s._onEnd(r,e,t,n,!0)},i)},detachDelegate:function(e,t,n,r){var i=t[v];i&&(i.detach(),t[v]=null),P(e)},detach:function(e,t,n){var r=t[h];r&&(r.detach(),t[h]=null),P(e)},processArgs:function(e,t){return A(this,e,t)},_onEnd:function(e,t,n,r,i){i&&(t=e[x]);var s=n._extra.standAlone||t.getData(g)||t.getData(m),o=n._extra.preventDefault;s&&(e.changedTouches&&(e.changedTouches.length===1?_(e,e.changedTouches[0]):s=!1),s&&(H(e,o),e.type=a,r.fire(e),t.clearData(m),t.clearData(g)))},PREVENT_DEFAULT:!1})},"3.7.3",{requires:["node-base","event-touch","event-synthetic"]});
diff --git a/js/yui3/event-outside/event-outside-min.js b/js/yui3/event-outside/event-outside-min.js
new file mode 100644
index 000000000..ec98c3424
--- /dev/null
+++ b/js/yui3/event-outside/event-outside-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-outside",function(e,t){var n=["blur","change","click","dblclick","focus","keydown","keypress","keyup","mousedown","mousemove","mouseout","mouseover","mouseup","select","submit"];e.Event.defineOutside=function(t,n){n=n||t+"outside";var r={on:function(n,r,i){r.handle=e.one("doc").on(t,function(e){this.isOutside(n,e.target)&&(e.currentTarget=n,i.fire(e))},this)},detach:function(e,t,n){t.handle.detach()},delegate:function(n,r,i,s){r.handle=e.one("doc").delegate(t,function(e){this.isOutside(n,e.target)&&i.fire(e)},s,this)},isOutside:function(e,t){return t!==e&&!t.ancestor(function(t){return t===e})}};r.detachDelegate=r.detach,e.Event.define(n,r)},e.Array.each(n,function(t){e.Event.defineOutside(t)})},"3.7.3",{requires:["event-synthetic"]});
diff --git a/js/yui3/event-resize/event-resize-min.js b/js/yui3/event-resize/event-resize-min.js
new file mode 100644
index 000000000..da8feed2e
--- /dev/null
+++ b/js/yui3/event-resize/event-resize-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-resize",function(e,t){e.Event.define("windowresize",{on:e.UA.gecko&&e.UA.gecko<1.91?function(t,n,r){n._handle=e.Event.attach("resize",function(e){r.fire(e)})}:function(t,n,r){var i=e.config.windowResizeDelay||100;n._handle=e.Event.attach("resize",function(t){n._timer&&n._timer.cancel(),n._timer=e.later(i,e,function(){r.fire(t)})})},detach:function(e,t){t._timer&&t._timer.cancel(),t._handle.detach()}})},"3.7.3",{requires:["node-base","event-synthetic"]});
diff --git a/js/yui3/event-simulate/event-simulate-min.js b/js/yui3/event-simulate/event-simulate-min.js
new file mode 100644
index 000000000..eaa183f1f
--- /dev/null
+++ b/js/yui3/event-simulate/event-simulate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-simulate",function(e,t){(function(){function p(t,u,a,f,l,c,h,p,d,v,m){t||e.error("simulateKeyEvent(): Invalid target.");if(r(u)){u=u.toLowerCase();switch(u){case"textevent":u="keypress";break;case"keyup":case"keydown":case"keypress":break;default:e.error("simulateKeyEvent(): Event type '"+u+"' not supported.")}}else e.error("simulateKeyEvent(): Event type must be a string.");i(a)||(a=!0),i(f)||(f=!0),s(l)||(l=e.config.win),i(c)||(c=!1),i(h)||(h=!1),i(p)||(p=!1),i(d)||(d=!1),o(v)||(v=0),o(m)||(m=0);var g=null;if(n(e.config.doc.createEvent)){try{g=e.config.doc.createEvent("KeyEvents"),g.initKeyEvent(u,a,f,l,c,h,p,d,v,m)}catch(y){try{g=e.config.doc.createEvent("Events")}catch(b){g=e.config.doc.createEvent("UIEvents")}finally{g.initEvent(u,a,f),g.view=l,g.altKey=h,g.ctrlKey=c,g.shiftKey=p,g.metaKey=d,g.keyCode=v,g.charCode=m}}t.dispatchEvent(g)}else s(e.config.doc.createEventObject)?(g=e.config.doc.createEventObject(),g.bubbles=a,g.cancelable=f,g.view=l,g.ctrlKey=c,g.altKey=h,g.shiftKey=p,g.metaKey=d,g.keyCode=m>0?m:v,t.fireEvent("on"+u,g)):e.error("simulateKeyEvent(): No event simulation framework present.")}function d(t,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S){t||e.error("simulateMouseEvent(): Invalid target."),r(a)?(a=a.toLowerCase(),u[a]||e.error("simulateMouseEvent(): Event type '"+a+"' not supported.")):e.error("simulateMouseEvent(): Event type must be a string."),i(f)||(f=!0),i(l)||(l=a!="mousemove"),s(c)||(c=e.config.win),o(h)||(h=1),o(p)||(p=0),o(d)||(d=0),o(v)||(v=0),o(m)||(m=0),i(g)||(g=!1),i(y)||(y=!1),i(b)||(b=!1),i(w)||(w=!1),o(E)||(E=0),S=S||null;var x=null;if(n(e.config.doc.createEvent))x=e.config.doc.createEvent("MouseEvents"),x.initMouseEvent?x.initMouseEvent(a,f,l,c,h,p,d,v,m,g,y,b,w,E,S):(x=e.config.doc.createEvent("UIEvents"),x.initEvent(a,f,l),x.view=c,x.detail=h,x.screenX=p,x.screenY=d,x.clientX=v,x.clientY=m,x.ctrlKey=g,x.altKey=y,x.metaKey=w,x.shiftKey=b,x.button=E,x.relatedTarget=S),S&&!x.relatedTarget&&(a=="mouseout"?x.toElement=S:a=="mouseover"&&(x.fromElement=S)),t.dispatchEvent(x);else if(s(e.config.doc.createEventObject)){x=e.config.doc.createEventObject(),x.bubbles=f,x.cancelable=l,x.view=c,x.detail=h,x.screenX=p,x.screenY=d,x.clientX=v,x.clientY=m,x.ctrlKey=g,x.altKey=y,x.metaKey=w,x.shiftKey=b;switch(E){case 0:x.button=1;break;case 1:x.button=4;break;case 2:break;default:x.button=0}x.relatedTarget=S,t.fireEvent("on"+a,x)}else e.error("simulateMouseEvent(): No event simulation framework present.")}function v(t,u,a,c,h,p){t||e.error("simulateUIEvent(): Invalid target."),r(u)?(u=u.toLowerCase(),f[u]||e.error("simulateUIEvent(): Event type '"+u+"' not supported.")):e.error("simulateUIEvent(): Event type must be a string.");var d=null;i(a)||(a=u in l),i(c)||(c=u=="submit"),s(h)||(h=e.config.win),o(p)||(p=1),n(e.config.doc.createEvent)?(d=e.config.doc.createEvent("UIEvents"),d.initUIEvent(u,a,c,h,p),t.dispatchEvent(d)):s(e.config.doc.createEventObject)?(d=e.config.doc.createEventObject(),d.bubbles=a,d.cancelable=c,d.view=h,d.detail=p,t.fireEvent("on"+u,d)):e.error("simulateUIEvent(): No event simulation framework present.")}function m(t,n,r,i,s,o,u,a,f,l,c,p,d,v,m,g){var y;(!e.UA.ios||e.UA.ios<2)&&e.error("simulateGestureEvent(): Native gesture DOM eventframe is not available in this platform."),t||e.error("simulateGestureEvent(): Invalid target."),e.Lang.isString(n)?(n=n.toLowerCase(),h[n]||e.error("simulateTouchEvent(): Event type '"+n+"' not supported.")):e.error("simulateGestureEvent(): Event type must be a string."),e.Lang.isBoolean(r)||(r=!0),e.Lang.isBoolean(i)||(i=!0),e.Lang.isObject(s)||(s=e.config.win),e.Lang.isNumber(o)||(o=2),e.Lang.isNumber(u)||(u=0),e.Lang.isNumber(a)||(a=0),e.Lang.isNumber(f)||(f=0),e.Lang.isNumber(l)||(l=0),e.Lang.isBoolean(c)||(c=!1),e.Lang.isBoolean(p)||(p=!1),e.Lang.isBoolean(d)||(d=!1),e.Lang.isBoolean(v)||(v=!1),e.Lang.isNumber(m)||(m=1),e.Lang.isNumber(g)||(g=0),y=e.config.doc.createEvent("GestureEvent"),y.initGestureEvent(n,r,i,s,o,u,a,f,l,c,p,d,v,t,m,g),t.dispatchEvent(y)}function g(t,n,r,i,s,o,u,a,f,l,h,p,d,v,m,g,y,b,w){var E;t||e.error("simulateTouchEvent(): Invalid target."),e.Lang.isString(n)?(n=n.toLowerCase(),c[n]||e.error("simulateTouchEvent(): Event type '"+n+"' not supported.")):e.error("simulateTouchEvent(): Event type must be a string."),n==="touchstart"||n==="touchmove"?m.length===0&&e.error("simulateTouchEvent(): No touch object in touches"):n==="touchend"&&y.length===0&&e.error("simulateTouchEvent(): No touch object in changedTouches"),e.Lang.isBoolean(r)||(r=!0),e.Lang.isBoolean(i)||(i=n!="touchcancel"),e.Lang.isObject(s)||(s=e.config.win),e.Lang.isNumber(o)||(o=1),e.Lang.isNumber(u)||(u=0),e.Lang.isNumber(a)||(a=0),e.Lang.isNumber(f)||(f=0),e.Lang.isNumber(l)||(l=0),e.Lang.isBoolean(h)||(h=!1),e.Lang.isBoolean(p)||(p=!1),e.Lang.isBoolean(d)||(d=!1),e.Lang.isBoolean(v)||(v=!1),e.Lang.isNumber(b)||(b=1),e.Lang.isNumber(w)||(w=0),e.Lang.isFunction(e.config.doc.createEvent)?(e.UA.android?e.UA.android<4?(E=e.config.doc.createEvent("MouseEvents"),E.initMouseEvent(n,r,i,s,o,u,a,f,l,h,p,d,v,0,t),E.touches=m,E.targetTouches=g,E.changedTouches=y):(E=e.config.doc.createEvent("TouchEvent"),E.initTouchEvent(m,g,y,n,s,u,a,f,l,h,p,d,v)):e.UA.ios?e.UA.ios>=2?(E=e.config.doc.createEvent("TouchEvent"),E.initTouchEvent(n,r,i,s,o,u,a,f,l,h,p,d,v,m,g,y,b,w)):e.error("simulateTouchEvent(): No touch event simulation framework present for iOS, "+e.UA.ios+"."):e.error("simulateTouchEvent(): Not supported agent yet, "+e.UA.userAgent),t.dispatchEvent(E)):e.error("simulateTouchEvent(): No event simulation framework present.")}var t=e.Lang,n=t.isFunction,r=t.isString,i=t.isBoolean,s=t.isObject,o=t.isNumber,u={click:1,dblclick:1,mouseover:1,mouseout:1,mousedown:1,mouseup:1,mousemove:1,contextmenu:1},a={keydown:1,keyup:1,keypress:1},f={submit:1,blur:1,change:1,focus:1,resize:1,scroll:1,select:1},l={scroll:1,resize:1,reset:1,submit:1,change:1,select:1,error:1,abort:1},c={touchstart:1,touchmove:1,touchend:1,touchcancel:1},h={gesturestart:1,gesturechange:1,gestureend:1};e.mix(l,u),e.mix(l,a),e.mix(l,c),e.Event.simulate=function(t,n,r){r=r||{},u[n]?d(t,n,r.bubbles,r.cancelable,r.view,r.detail,r.screenX,r.screenY,r.clientX,r.clientY,r.ctrlKey,r.altKey,r.shiftKey,r.metaKey,r.button,r.relatedTarget):a[n]?p(t,n,r.bubbles,r.cancelable,r.view,r.ctrlKey,r.altKey,r.shiftKey,r.metaKey,r.keyCode,r.charCode):f[n]?v(t,n,r.bubbles,r.cancelable,r.view,r.detail):c[n]?e.config.win&&"ontouchstart"in e.config.win&&!e.UA.phantomjs&&!(e.UA.chrome&&e.UA.chrome<6)?g(t,n,r.bubbles,r.cancelable,r.view,r.detail,r.screenX,r.screenY,r.clientX,r.clientY,r.ctrlKey,r.altKey,r.shiftKey,r.metaKey,r.touches,r.targetTouches,r.changedTouches,r.scale,r.rotation):e.error("simulate(): Event '"+n+"' can't be simulated. Use gesture-simulate module instead."):e.UA.ios&&e.UA.ios>=2&&h[n]?m(t,n,r.bubbles,r.cancelable,r.view,r.detail,r.screenX,r.screenY,r.clientX,r.clientY,r.ctrlKey,r.altKey,r.shiftKey,r.metaKey,r.scale,r.rotation):e.error("simulate(): Event '"+n+"' can't be simulated.")}})()},"3.7.3",{requires:["event-base"]});
diff --git a/js/yui3/event-synthetic/event-synthetic-min.js b/js/yui3/event-synthetic/event-synthetic-min.js
new file mode 100644
index 000000000..c6927735b
--- /dev/null
+++ b/js/yui3/event-synthetic/event-synthetic-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-synthetic",function(e,t){function c(e,t){this.handle=e,this.emitFacade=t}function h(e,t,n){this.handles=[],this.el=e,this.key=n,this.domkey=t}function p(){this._init.apply(this,arguments)}var n=e.CustomEvent,r=e.Env.evt.dom_map,i=e.Array,s=e.Lang,o=s.isObject,u=s.isString,a=s.isArray,f=e.Selector.query,l=function(){};c.prototype.fire=function(t){var n=i(arguments,0,!0),r=this.handle,s=r.evt,u=r.sub,a=u.context,f=u.filter,l=t||{},c;if(this.emitFacade){if(!t||!t.preventDefault)l=s._getFacade(),o(t)&&!t.preventDefault?(e.mix(l,t,!0),n[0]=l):n.unshift(l);l.type=s.type,l.details=n.slice(),f&&(l.container=s.host)}else f&&o(t)&&t.currentTarget&&n.shift();return u.context=a||l.currentTarget||s.host,c=s.fire.apply(s,n),u.context=a,c},h.prototype={constructor:h,type:"_synth",fn:l,capture:!1,register:function(e){e.evt.registry=this,this.handles.push(e)},unregister:function(t){var n=this.handles,i=r[this.domkey],s;for(s=n.length-1;s>=0;--s)if(n[s].sub===t){n.splice(s,1);break}n.length||(delete i[this.key],e.Object.size(i)||delete r[this.domkey])},detachAll:function(){var e=this.handles,t=e.length;while(--t>=0)e[t].detach()}},e.mix(p,{Notifier:c,SynthRegistry:h,getRegistry:function(t,n,i){var s=t._node,o=e.stamp(s),u="event:"+o+n+"_synth",a=r[o];return i&&(a||(a=r[o]={}),a[u]||(a[u]=new h(s,o,u))),a&&a[u]||null},_deleteSub:function(e){if(e&&e.fn){var t=this.eventDef,r=e.filter?"detachDelegate":"detach";this._subscribers=[],n.keepDeprecatedSubs&&(this.subscribers={}),t[r](e.node,e,this.notifier,e.filter),this.registry.unregister(e),delete e.fn,delete e.node,delete e.context}},prototype:{constructor:p,_init:function(){var e=this.publishConfig||(this.publishConfig={});this.emitFacade="emitFacade"in e?e.emitFacade:!0,e.emitFacade=!1},processArgs:l,on:l,detach:l,delegate:l,detachDelegate:l,_on:function(t,n){var r=[],s=t.slice(),o=this.processArgs(t,n),a=t[2],l=n?"delegate":"on",c,h;return c=u(a)?f(a):i(a||e.one(e.config.win)),!c.length&&u(a)?(h=e.on("available",function(){e.mix(h,e[l].apply(e,s),!0)},a),h):(e.Array.each(c,function(i){var s=t.slice(),u;i=e.one(i),i&&(n&&(u=s.splice(3,1)[0]),s.splice(0,4,s[1],s[3]),(!this.preventDups||!this.getSubs(i,t,null,!0))&&r.push(this._subscribe(i,l,s,o,u)))},this),r.length===1?r[0]:new e.EventHandle(r))},_subscribe:function(t,n,r,i,s){var o=new e.CustomEvent(this.type,this.publishConfig),u=o.on.apply(o,r),a=new c(u,this.emitFacade),f=p.getRegistry(t,this.type,!0),l=u.sub;return l.node=t,l.filter=s,i&&this.applyArgExtras(i,l),e.mix(o,{eventDef:this,notifier:a,host:t,currentTarget:t,target:t,el:t._node,_delete:p._deleteSub},!0),u.notifier=a,f.register(u),this[n](t,l,a,s),u},applyArgExtras:function(e,t){t._extra=e},_detach:function(t){var n=t[2],r=u(n)?f(n):i(n),s,o,a,l,c;t.splice(2,1);for(o=0,a=r.length;o<a;++o){s=e.one(r[o]);if(s){l=this.getSubs(s,t);if(l)for(c=l.length-1;c>=0;--c)l[c].detach()}}},getSubs:function(e,t,n,r){var i=p.getRegistry(e,this.type),s=[],o,u,a,f;if(i){o=i.handles,n||(n=this.subMatch);for(u=0,a=o.length;u<a;++u){f=o[u];if(n.call(this,f.sub,t)){if(r)return f;s.push(o[u])}}}return s.length&&s},subMatch:function(e,t){return!t[1]||e.fn===t[1]}}},!0),e.SyntheticEvent=p,e.Event.define=function(t,n,r){var s,o,f;t&&t.type?(s=t,r=n):n&&(s=e.merge({type:t},n));if(s){if(r||!e.Node.DOM_EVENTS[s.type])o=function(){p.apply(this,arguments)},e.extend(o,p,s),f=new o,t=f.type,e.Node.DOM_EVENTS[t]=e.Env.evt.plugins[t]={eventDef:f,on:function(){return f._on(i(arguments))},delegate:function(){return f._on(i(arguments),!0)},detach:function(){return f._detach(i(arguments))}}}else(u(t)||a(t))&&e.Array.each(i(t),function(t){e.Node.DOM_EVENTS[t]=1});return f}},"3.7.3",{requires:["node-base","event-custom-complex"]});
diff --git a/js/yui3/event-tap/event-tap-min.js b/js/yui3/event-tap/event-tap-min.js
new file mode 100644
index 000000000..7ca5c7452
--- /dev/null
+++ b/js/yui3/event-tap/event-tap-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-tap",function(e,t){function l(t,n,r,i){n=r?n:[n.START,n.MOVE,n.END,n.CANCEL],e.Array.each(n,function(e,n,r){var i=t[e];i&&(i.detach(),t[e]=null)})}var n=e.config.doc,r=!!n&&!!n.createTouch,i=r?"touchstart":"mousedown",s=r?"touchmove":"mousemove",o=r?"touchend":"mouseup",u=r?"touchcancel":"mousecancel",a="tap",f={START:"Y_TAP_ON_START_HANDLE",MOVE:"Y_TAP_ON_MOVE_HANDLE",END:"Y_TAP_ON_END_HANDLE",CANCEL:"Y_TAP_ON_CANCEL_HANDLE"};e.Event.define(a,{on:function(e,t,n){t[f.START]=e.on(i,this.touchStart,this,e,t,n)},detach:function(e,t,n){l(t,f)},delegate:function(e,t,n,r){t[f.START]=e.delegate(i,function(r){this.touchStart(r,e,t,n,!0)},r,this)},detachDelegate:function(e,t,n){l(t,f)},touchStart:function(e,t,n,i,a){var l={canceled:!1};if(e.button&&e.button===3)return;if(e.touches&&e.touches.length!==1)return;l.node=a?e.currentTarget:t,r&&e.touches?l.startXY=[e.touches[0].pageX,e.touches[0].pageY]:l.startXY=[e.pageX,e.pageY],n[f.MOVE]=t.once(s,this.touchMove,this,t,n,i,a,l),n[f.END]=t.once(o,this.touchEnd,this,t,n,i,a,l),n[f.CANCEL]=t.once(u,this.touchMove,this,t,n,i,a,l)},touchMove:function(e,t,n,r,i,s){l(n,[f.MOVE,f.END,f.CANCEL],!0,s),s.cancelled=!0},touchEnd:function(e,t,n,i,s,o){var u=o.startXY,c,h;r&&e.changedTouches?(c=[e.changedTouches[0].pageX,e.changedTouches[0].pageY],h=[e.changedTouches[0].clientX,e.changedTouches[0].clientY]):(c=[e.pageX,e.pageY],h=[e.clientX,e.clientY]),l(n,[f.MOVE,f.END,f.CANCEL],!0,o),Math.abs(c[0]-u[0])===0&&Math.abs(c[1]-u[1])===0&&(e.type=a,e.pageX=c[0],e.pageY=c[1],e.clientX=h[0],e.clientY=h[1],e.currentTarget=o.node,i.fire(e))}})},"3.7.3",{requires:["node-base","event-base","event-touch","event-synthetic"]});
diff --git a/js/yui3/event-touch/event-touch-min.js b/js/yui3/event-touch/event-touch-min.js
new file mode 100644
index 000000000..e54607be5
--- /dev/null
+++ b/js/yui3/event-touch/event-touch-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-touch",function(e,t){var n="scale",r="rotation",i="identifier",s=e.config.win,o={};e.DOMEventFacade.prototype._touch=function(t,s,o){var u,a,f,l,c;if(t.touches){this.touches=[],c={};for(u=0,a=t.touches.length;u<a;++u)l=t.touches[u],c[e.stamp(l)]=this.touches[u]=new e.DOMEventFacade(l,s,o)}if(t.targetTouches){this.targetTouches=[];for(u=0,a=t.targetTouches.length;u<a;++u)l=t.targetTouches[u],f=c&&c[e.stamp(l,!0)],this.targetTouches[u]=f||new e.DOMEventFacade(l,s,o)}if(t.changedTouches){this.changedTouches=[];for(u=0,a=t.changedTouches.length;u<a;++u)l=t.changedTouches[u],f=c&&c[e.stamp(l,!0)],this.changedTouches[u]=f||new e.DOMEventFacade(l,s,o)}n in t&&(this[n]=t[n]),r in t&&(this[r]=t[r]),i in t&&(this[i]=t[i])},e.Node.DOM_EVENTS&&e.mix(e.Node.DOM_EVENTS,{touchstart:1,touchmove:1,touchend:1,touchcancel:1,gesturestart:1,gesturechange:1,gestureend:1,MSPointerDown:1,MSPointerUp:1,MSPointerMove:1}),s&&"ontouchstart"in s&&!(e.UA.chrome&&e.UA.chrome<6)?(o.start="touchstart",o.end="touchend",o.move="touchmove"):s&&"msPointerEnabled"in s.navigator?(o.start="MSPointerDown",o.end="MSPointerUp",o.move="MSPointerMove"):(o.start="mousedown",o.end="mouseup",o.move="mousemove"),e.Event._GESTURE_MAP=o},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/event-valuechange/event-valuechange-min.js b/js/yui3/event-valuechange/event-valuechange-min.js
new file mode 100644
index 000000000..047aec0ba
--- /dev/null
+++ b/js/yui3/event-valuechange/event-valuechange-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("event-valuechange",function(e,t){var n="_valuechange",r="value",i,s={POLL_INTERVAL:50,TIMEOUT:1e4,_poll:function(t,r){var i=t._node,o=r.e,u=i&&i.value,a=t._data&&t._data[n],f,l;if(!i||!a){s._stopPolling(t);return}l=a.prevVal,u!==l&&(a.prevVal=u,f={_event:o,currentTarget:o&&o.currentTarget||t,newVal:u,prevVal:l,target:o&&o.target||t},e.Object.each(a.notifiers,function(e){e.fire(f)}),s._refreshTimeout(t))},_refreshTimeout:function(e,t){if(!e._node)return;var r=e.getData(n);s._stopTimeout(e),r.timeout=setTimeout(function(){s._stopPolling(e,t)},s.TIMEOUT)},_startPolling:function(t,i,o){if(!t.test("input,textarea"))return;var u=t.getData(n);u||(u={prevVal:t.get(r)},t.setData(n,u)),u.notifiers||(u.notifiers={});if(u.interval){if(!o.force){u.notifiers[e.stamp(i)]=i;return}s._stopPolling(t,i)}u.notifiers[e.stamp(i)]=i,u.interval=setInterval(function(){s._poll(t,u,o)},s.POLL_INTERVAL),s._refreshTimeout(t,i)},_stopPolling:function(t,r){if(!t._node)return;var i=t.getData(n)||{};clearInterval(i.interval),delete i.interval,s._stopTimeout(t),r?i.notifiers&&delete i.notifiers[e.stamp(r)]:i.notifiers={}},_stopTimeout:function(e){var t=e.getData(n)||{};clearTimeout(t.timeout),delete t.timeout},_onBlur:function(e,t){s._stopPolling(e.currentTarget,t)},_onFocus:function(e,t){var i=e.currentTarget,o=i.getData(n);o||(o={},i.setData(n,o)),o.prevVal=i.get(r),s._startPolling(i,t,{e:e})},_onKeyDown:function(e,t){s._startPolling(e.currentTarget,t,{e:e})},_onKeyUp:function(e,t){(e.charCode===229||e.charCode===197)&&s._startPolling(e.currentTarget,t,{e:e,force:!0})},_onMouseDown:function(e,t){s._startPolling(e.currentTarget,t,{e:e})},_onSubscribe:function(t,i,o,u){var a,f,l;f={blur:s._onBlur,focus:s._onFocus,keydown:s._onKeyDown,keyup:s._onKeyUp,mousedown:s._onMouseDown},a=o._valuechange={};if(u)a.delegated=!0,a.getNodes=function(){return t.all("input,textarea").filter(u)},a.getNodes().each(function(e){e.getData(n)||e.setData(n,{prevVal:e.get(r)})}),o._handles=e.delegate(f,t,u,null,o);else{if(!t.test("input,textarea"))return;t.getData(n)||t.setData(n,{prevVal:t.get(r)}),o._handles=t.on(f,null,null,o)}},_onUnsubscribe:function(e,t,n){var r=n._valuechange;n._handles&&n._handles.detach(),r.delegated?r.getNodes().each(function(e){s._stopPolling(e,n)}):s._stopPolling(e,n)}};i={detach:s._onUnsubscribe,on:s._onSubscribe,delegate:s._onSubscribe,detachDelegate:s._onUnsubscribe,publishConfig:{emitFacade:!0}},e.Event.define("valuechange",i),e.Event.define("valueChange",i),e.ValueChange=s},"3.7.3",{requires:["event-focus","event-synthetic"]});
diff --git a/js/yui3/exec-command/exec-command-min.js b/js/yui3/exec-command/exec-command-min.js
new file mode 100644
index 000000000..4c7752e7c
--- /dev/null
+++ b/js/yui3/exec-command/exec-command-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("exec-command",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r=function(t,n,r){var i=this.getInstance(),s=i.config.doc,o=s.selection.createRange(),u=s.queryCommandValue(t),a,f,l,c,h,p,d;u&&(a=o.htmlText,f=new RegExp(r,"g"),l=a.match(f),l&&(a=a.replace(r+";","").replace(r,""),o.pasteHTML('<var id="yui-ie-bs">'),c=s.getElementById("yui-ie-bs"),h=s.createElement("div"),p=s.createElement(n),h.innerHTML=a,c.parentNode!==i.config.doc.body&&(c=c.parentNode),d=h.childNodes,c.parentNode.replaceChild(p,c),e.each(d,function(e){p.appendChild(e)}),o.collapse(),o.moveToElementText&&o.moveToElementText(p),o.select())),this._command(t)};e.extend(n,e.Base,{_lastKey:null,_inst:null,command:function(e,t){var r=n.COMMANDS[e];return r?r.call(this,e,t):this._command(e,t)},_command:function(e,t){var n=this.getInstance();try{try{n.config.doc.execCommand("styleWithCSS",null,1)}catch(r){try{n.config.doc.execCommand("useCSS",null,0)}catch(i){}}n.config.doc.execCommand(e,null,t)}catch(s){}},getInstance:function(){return this._inst||(this._inst=this.get("host").getInstance()),this._inst},initializer:function(){e.mix(this.get("host"),{execCommand:function(e,t){return this.exec.command(e,t)},_execCommand:function(e,t){return this.exec._command(e,t)}}),this.get("host").on("dom:keypress",e.bind(function(e){this._lastKey=e.keyCode},this))},_wrapContent:function(e,t){var n=this.getInstance().host.editorPara&&!t?!0:!1;return n?e="<p>"+e+"</p>":e+="<br>",e}},{NAME:"execCommand",NS:"exec",ATTRS:{host:{value:!1}},COMMANDS:{wrap:function(e,t){var n=this.getInstance();return(new n.EditorSelection).wrapContent(t)},inserthtml:function(t,n){var r=this.getInstance();if(r.EditorSelection.hasCursor()||e.UA.ie)return(new r.EditorSelection).insertContent(n);this._command("inserthtml",n)},insertandfocus:function(e,t){var n=this.getInstance(),r,i;return n.EditorSelection.hasCursor()?(t+=n.EditorSelection.CURSOR,r=this.command("inserthtml",t),i=new n.EditorSelection,i.focusCursor(!0,!0)):this.command("inserthtml",t),r},insertbr:function(){var t=this.getInstance(),n=new t.EditorSelection,r="<var>|</var>",i=null,s=e.UA.webkit?"span.Apple-style-span,var":"var",o=function(e){var n=t.Node.create("<br>");return e.insert(n,"before"),n};n._selection.pasteHTML?n._selection.pasteHTML(r):this._command("inserthtml",r),t.all(s).each(function(t){var n=!0,r;e.UA.webkit&&(n=!1,t.get("innerHTML")==="|"&&(n=!0)),n&&(i=o(t),(!i.previous()||!i.previous().test("br"))&&e.UA.gecko&&(r=i.cloneNode(),i.insert(r,"after"),i=r),t.remove())}),e.UA.webkit&&i&&(o(i),n.selectNode(i))},insertimage:function(e,t){return this.command("inserthtml",'<img src="'+t+'">')},addclass:function(e,t){var n=this.getInstance();return(new n.EditorSelection).getSelected().addClass(t)},removeclass:function(e,t){var n=this.getInstance();return(new n.EditorSelection).getSelected().removeClass(t)},forecolor:function(t,n){var r=this.getInstance(),i=new r.EditorSelection,s;e.UA.ie||this._command("useCSS",!1);if(r.EditorSelection.hasCursor())return i.isCollapsed?(i.anchorNode&&i.anchorNode.get("innerHTML")==="&nbsp;"?(i.anchorNode.setStyle("color",n),s=i.anchorNode):(s=this.command("inserthtml",'<span style="color: '+n+'">'+r.EditorSelection.CURSOR+"</span>"),i.focusCursor(!0,!0)),s):this._command(t,n);this._command(t,n)},backcolor:function(t,n){var r=this.getInstance(),i=new r.EditorSelection,s;if(e.UA.gecko||e.UA.opera)t="hilitecolor";e.UA.ie||this._command("useCSS",!1);if(r.EditorSelection.hasCursor())return i.isCollapsed?(i.anchorNode&&i.anchorNode.get("innerHTML")==="&nbsp;"?(i.anchorNode.setStyle("backgroundColor",n),s=i.anchorNode):(s=this.command("inserthtml",'<span style="background-color: '+n+'">'+r.EditorSelection.CURSOR+"</span>"),i.focusCursor(!0,!0)),s):this._command(t,n);this._command(t,n)},hilitecolor:function(){return n.COMMANDS.backcolor.apply(this,arguments)},fontname2:function(e,t){this._command("fontname",t);var n=this.getInstance(),r=new n.EditorSelection;r.isCollapsed&&this._lastKey!==32&&r.anchorNode.test("font")&&r.anchorNode.set("face",t)},fontsize2:function(t,n){this._command("fontsize",n);var r=this.getInstance(),i=new r.EditorSelection,s;i.isCollapsed&&i.anchorNode&&this._lastKey!==32&&(e.UA.webkit&&i.anchorNode.getStyle("lineHeight")&&i.anchorNode.setStyle("lineHeight",""),i.anchorNode.test("font")?i.anchorNode.set("size",n):e.UA.gecko&&(s=i.anchorNode.ancestor(r.EditorSelection.DEFAULT_BLOCK_TAG),s&&s.setStyle("fontSize","")))},insertunorderedlist:function(){this.command("list","ul")},insertorderedlist:function(){this.command("list","ol")},list:function(t,n){var r=this.getInstance(),i,s=this,o="dir",u="yui3-touched",a,f,l,c,h,p,d,v,m,g,y=r.host.editorPara?!0:!1,b,w,E,S,x=new r.EditorSelection;t="insert"+(n==="ul"?"un":"")+"orderedlist";if(e.UA.ie&&!x.isCollapsed){f=x._selection,i=f.htmlText,l=r.Node.create(i)||r.one("body");if(l.test("li")||l.one("li")){this._command(t,null);return}l.test(n)?(c=f.item?f.item(0):f.parentElement(),h=r.one(c),g=h.all("li"),p="<div>",g.each(function(e){p=s._wrapContent(e.get("innerHTML"))}),p+="</div>",d=r.Node.create(p),h.get("parentNode").test("div")&&(h=h.get("parentNode")),h&&h.hasAttribute(o)&&(y?d.all("p").setAttribute(o,h.getAttribute(o)):d.setAttribute(o,h.getAttribute(o))),y?h.replace(d.get("innerHTML")):h.replace(d),f.moveToElementText&&f.moveToElementText(d._node),f.select()):(v=e.one(f.parentElement()),v.test(r.EditorSelection.BLOCKS)||(v=v.ancestor(r.EditorSelection.BLOCKS)),v&&v.hasAttribute(o)&&(a=v.getAttribute(o)),i.indexOf("<br>")>-1?i=i.split(/<br>/i):(b=r.Node.create(i),ps=b?b.all("p"):null,ps&&ps.size()?(i=[],ps.each(function(e){i.push(e.get("innerHTML"))})):i=[i]),m="<"+n+' id="ie-list">',e.each(i,function(e){var t=r.Node.create(e);t&&t.test("p")&&(t.hasAttribute(o)&&(a=t.getAttribute(o)),e=t.get("innerHTML")),m+="<li>"+e+"</li>"}),m+="</"+n+">",f.pasteHTML(m),c=r.config.doc.getElementById("ie-list"),c.id="",a&&c.setAttribute(o,a),f.moveToElementText&&f.moveToElementText(c),f.select())}else e.UA.ie?(v=r.one(x._selection.parentElement()),v.test("p")?(v&&v.hasAttribute(o)&&(a=v.getAttribute(o)),i=e.EditorSelection.getText(v),i===""?(w="",a&&(w=' dir="'+a+'"'),m=r.Node.create(e.Lang.sub("<{tag}{dir}><li></li></{tag}>",{tag:n,dir:w})),v.replace(m),x.selectNode(m.one("li"))):this._command(t,null)):this._command(t,null)):(r.all(n).addClass(u),x.anchorNode.test(r.EditorSelection.BLOCKS)?v=x.anchorNode:v=x.anchorNode.ancestor(r.EditorSelection.BLOCKS),v||(v=x.anchorNode.one(r.EditorSelection.BLOCKS)),v&&v.hasAttribute(o)&&(a=v.getAttribute(o)),v&&v.test(n)?(E=v.ancestor("p"),i=r.Node.create("<div/>"),c=v.all("li"),c.each(function(e){i.append(s._wrapContent(e.get("innerHTML"),E))}),a&&(y?i.all("p").setAttribute(o,a):i.setAttribute(o,a)),y&&(i=r.Node.create(i.get("innerHTML"))),S=i.get("firstChild"),v.replace(i),x.selectNode(S)):this._command(t,null),m=r.all(n),a&&m.size()&&m.each(function(e){e.hasClass(u)||e.setAttribute(o,a)}),m.removeClass(u))},justify:function(t,n){if(e.UA.webkit){var r=this.getInstance(),i=new r.EditorSelection,s=i.anchorNode,o,u=s.getStyle("backgroundColor");this._command(n),i=new r.EditorSelection,i.anchorNode.test("div")&&(o="<span>"+i.anchorNode.get("innerHTML")+"</span>",i.anchorNode.set("innerHTML",o),i.anchorNode.one("span").setStyle("backgroundColor",u),i.selectNode(i.anchorNode.one("span")))}else this._command(n)},justifycenter:function(){this.command("justify","justifycenter")},justifyleft:function(){this.command("justify","justifyleft")},justifyright:function(){this.command("justify","justifyright")},justifyfull:function(){this.command("justify","justifyfull")}}}),e.UA.ie&&(n.COMMANDS.bold=function(){r.call(this,"bold","b","FONT-WEIGHT: bold")},n.COMMANDS.italic=function(){r.call(this,"italic","i","FONT-STYLE: italic")},n.COMMANDS.underline=function(){r.call(this,"underline","u","TEXT-DECORATION: underline")}),e.namespace("Plugin"),e.Plugin.ExecCommand=n},"3.7.3",{requires:["frame"]});
diff --git a/js/yui3/features/features-min.js b/js/yui3/features/features-min.js
new file mode 100644
index 000000000..bd6633b89
--- /dev/null
+++ b/js/yui3/features/features-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/file-flash/file-flash-min.js b/js/yui3/file-flash/file-flash-min.js
new file mode 100644
index 000000000..4772908b3
--- /dev/null
+++ b/js/yui3/file-flash/file-flash-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("file-flash",function(e,t){var n=function(e){n.superclass.constructor.apply(this,arguments)};e.extend(n,e.Base,{initializer:function(t){this.get("id")||this._set("id",e.guid("file"))},_swfEventHandler:function(e){if(e.id===this.get("id"))switch(e.type){case"uploadstart":this.fire("uploadstart",{uploader:this.get("uploader")});break;case"uploadprogress":this.fire("uploadprogress",{originEvent:e,bytesLoaded:e.bytesLoaded,bytesTotal:e.bytesTotal,percentLoaded:Math.min(100,Math.round(1e4*e.bytesLoaded/e.bytesTotal)/100)}),this._set("bytesUploaded",e.bytesLoaded);break;case"uploadcomplete":this.fire("uploadfinished",{originEvent:e});break;case"uploadcompletedata":this.fire("uploadcomplete",{originEvent:e,data:e.data});break;case"uploadcancel":this.fire("uploadcancel",{originEvent:e});break;case"uploaderror":this.fire("uploaderror",{originEvent:e,status:e.status,statusText:e.message,source:e.source})}},startUpload:function(e,t,n){if(this.get("uploader")){var r=this.get("uploader"),i=n||"Filedata",s=this.get("id"),o=t||null;this._set("bytesUploaded",0),r.on("uploadstart",this._swfEventHandler,this),r.on("uploadprogress",this._swfEventHandler,this),r.on("uploadcomplete",this._swfEventHandler,this),r.on("uploadcompletedata",this._swfEventHandler,this),r.on("uploaderror",this._swfEventHandler,this),r.callSWF("upload",[s,e,o,i])}},cancelUpload:function(){this.get("uploader")&&(this.get("uploader").callSWF("cancel",[this.get("id")]),this.fire("uploadcancel"))}},{NAME:"file",TYPE:"flash",ATTRS:{id:{writeOnce:"initOnly",value:null},size:{writeOnce:"initOnly",value:0},name:{writeOnce:"initOnly",value:null},dateCreated:{writeOnce:"initOnly",value:null},dateModified:{writeOnce:"initOnly",value:null},bytesUploaded:{readOnly:!0,value:0},type:{writeOnce:"initOnly",value:null},uploader:{writeOnce:"initOnly",value:null}}}),e.FileFlash=n},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/file-html5/file-html5-min.js b/js/yui3/file-html5/file-html5-min.js
new file mode 100644
index 000000000..65e17271a
--- /dev/null
+++ b/js/yui3/file-html5/file-html5-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("file-html5",function(e,t){var n=e.Lang,r=e.bind,i=e.config.win,s=function(e){var t=null;s.isValidFile(e)?t=e:s.isValidFile(e.file)?t=e.file:t=!1,s.superclass.constructor.apply(this,arguments),t&&s.canUpload()&&(this.get("file")||this._set("file",t),this.get("name")||this._set("name",t.name||t.fileName),this.get("size")!=(t.size||t.fileSize)&&this._set("size",t.size||t.fileSize),this.get("type")||this._set("type",t.type),t.hasOwnProperty("lastModifiedDate")&&!this.get("dateModified")&&this._set("dateModified",t.lastModifiedDate))};e.extend(s,e.Base,{initializer:function(t){this.get("id")||this._set("id",e.guid("file"))},_uploadEventHandler:function(e){var t=this.get("xhr");switch(e.type){case"progress":this.fire("uploadprogress",{originEvent:e,bytesLoaded:e.loaded,bytesTotal:this.get("size"),percentLoaded:Math.min(100,Math.round(1e4*e.loaded/this.get("size"))/100)}),this._set("bytesUploaded",e.loaded);break;case"load":if(t.status>=200&&t.status<=299){this.fire("uploadcomplete",{originEvent:e,data:e.target.responseText});var n=t.upload,r=this.get("boundEventHandler");n.removeEventListener("progress",r),n.removeEventListener("error",r),n.removeEventListener("abort",r),t.removeEventListener("load",r),t.removeEventListener("error",r),t.removeEventListener("readystatechange",r),this._set("xhr",null)}else this.fire("uploaderror",{originEvent:e,status:t.status,statusText:t.statusText,source:"http"});break;case"error":this.fire("uploaderror",{originEvent:e,status:t.status,statusText:t.statusText,source:"io"});break;case"abort":this.fire("uploadcancel",{originEvent:e});break;case"readystatechange":this.fire("readystatechange",{readyState:e.target.readyState,originEvent:e})}},startUpload:function(t,n,i){this._set("bytesUploaded",0),this._set("xhr",new XMLHttpRequest),this._set("boundEventHandler",r(this._uploadEventHandler,this));var s=new FormData,o=i||"Filedata",u=this.get("xhr"),a=this.get("xhr").upload,f=this.get("boundEventHandler");e.each(n,function(e,t){s.append(t,e)}),s.append(o,this.get("file")),u.addEventListener("loadstart",f,!1),a.addEventListener("progress",f,!1),u.addEventListener("load",f,!1),u.addEventListener("error",f,!1),a.addEventListener("error",f,!1),a.addEventListener("abort",f,!1),u.addEventListener("abort",f,!1),u.addEventListener("loadend",f,!1),u.addEventListener("readystatechange",f,!1),u.open("POST",t,!0),u.withCredentials=this.get("xhrWithCredentials"),e.each(this.get("xhrHeaders"),function(e,t){u.setRequestHeader(t,e)}),u.send(s),this.fire("uploadstart",{xhr:u})},cancelUpload:function(){this.get("xhr").abort()}},{NAME:"file",TYPE:"html5",ATTRS:{id:{writeOnce:"initOnly",value:null},size:{writeOnce:"initOnly",value:0},name:{writeOnce:"initOnly",value:null},dateCreated:{writeOnce:"initOnly",value:null},dateModified:{writeOnce:"initOnly",value:null},bytesUploaded:{readOnly:!0,value:0},type:{writeOnce:"initOnly",value:null},file:{writeOnce:"initOnly",value:null},xhr:{readOnly:!0,value:null},xhrHeaders:{value:{}},xhrWithCredentials:{value:!0},boundEventHandler:{readOnly:!0,value:null}},isValidFile:function(e){return i&&i.File&&e instanceof File},canUpload:function(){return i&&i.FormData&&i.XMLHttpRequest}}),e.FileHTML5=s},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/file/file-min.js b/js/yui3/file/file-min.js
new file mode 100644
index 000000000..0c766d4ba
--- /dev/null
+++ b/js/yui3/file/file-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("file",function(e,t){var n=e.config.win;n&&n.File&&n.FormData&&n.XMLHttpRequest?e.File=e.FileHTML5:e.File=e.FileFlash},"3.7.3",{requires:["file-flash","file-html5"]});
diff --git a/js/yui3/frame/frame-min.js b/js/yui3/frame/frame-min.js
new file mode 100644
index 000000000..a8b2b73a5
--- /dev/null
+++ b/js/yui3/frame/frame-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("frame",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.extend(n,e.Base,{_ready:null,_rendered:null,_iframe:null,_instance:null,_create:function(t){var r,i="",s,o=this.get("src")===n.ATTRS.src.value,u=this.get("extracss")?'<style id="extra_css">'+this.get("extracss")+"</style>":"";this._iframe=e.one(e.config.doc.createElement("iframe")),this._iframe.setAttrs(n.IFRAME_ATTRS),this._iframe.setStyle("visibility","hidden"),this._iframe.set("src",this.get("src")),this.get("container").append(this._iframe),this._iframe.set("height","99%"),o&&(i=e.Lang.sub(n.PAGE_HTML,{DIR:this.get("dir"),LANG:this.get("lang"),TITLE:this.get("title"),META:n.META,LINKED_CSS:this.get("linkedcss"),CONTENT:this.get("content"),BASE_HREF:this.get("basehref"),DEFAULT_CSS:n.DEFAULT_CSS,EXTRA_CSS:u}),e.config.doc.compatMode!=="BackCompat"&&(i=n.getDocType()+"\n"+i)),r=this._resolveWinDoc(),i&&(r.doc.open(),r.doc.write(i),r.doc.close()),r.doc.documentElement?t(r):s=e.later(1,this,function(){r.doc&&r.doc.documentElement&&(t(r),s.cancel())},null,!0)},_resolveWinDoc:function(t){var n=t?t:{};return n.win=e.Node.getDOMNode(this._iframe.get("contentWindow")),n.doc=e.Node.getDOMNode(this._iframe.get("contentWindow.document")),n.doc||(n.doc=e.config.doc),n.win||(n.win=e.config.win),n},_onDomEvent:function(t){var n,r;if(!e.Node.getDOMNode(this._iframe))return;t.frameX=t.frameY=0,(t.pageX>0||t.pageY>0)&&t.type.substring(0,3)!=="key"&&(r=this._instance.one("win"),n=this._iframe.getXY(),t.frameX=n[0]+t.pageX-r.get("scrollLeft"),t.frameY=n[1]+t.pageY-r.get("scrollTop")),t.frameTarget=t.target,t.frameCurrentTarget=t.currentTarget,t.frameEvent=t,this.fire("dom:"+t.type,t)},initializer:function(){this.publish("ready",{emitFacade:!0,defaultFn:this._defReadyFn})},destructor:function(){var e=this.getInstance();e.one("doc").detachAll(),e=null,this._iframe.remove()},_DOMPaste:function(e){var t=this.getInstance(),n="",r=t.config.win;e._event.originalTarget&&(n=e._event.originalTarget),e._event.clipboardData&&(n=e._event.clipboardData.getData("Text")),r.clipboardData&&(n=r.clipboardData.getData("Text"),n===""&&(r.clipboardData.setData("Text",n)||(n=null))),e.frameTarget=e.target,e.frameCurrentTarget=e.currentTarget,e.frameEvent=e,n?e.clipboardData={data:n,getData:function(){return n}}:e.clipboardData=null,this.fire("dom:paste",e)},_defReadyFn:function(){var t=this.getInstance();e.each(n.DOM_EVENTS,function(r,i){var s=e.bind(this._onDomEvent,this),o=e.UA.ie&&n.THROTTLE_TIME>0?e.throttle(s,n.THROTTLE_TIME):s;t.Node.DOM_EVENTS[i]||(t.Node.DOM_EVENTS[i]=1),r===1&&i!=="focus"&&i!=="blur"&&i!=="paste"&&(i.substring(0,3)==="key"?t.on(i,o,t.config.doc):t.on(i,s,t.config.doc))},this),t.Node.DOM_EVENTS.paste=1,t.on("paste",e.bind(this._DOMPaste,this),t.one("body")),t.on("focus",e.bind(this._onDomEvent,this),t.config.win),t.on("blur",e.bind(this._onDomEvent,this),t.config.win),t.__use=t.use,t.use=e.bind(this.use,this),this._iframe.setStyles({visibility:"inherit"}),t.one("body").setStyle("display","block")},_fixIECursors:function(){var e=this.getInstance(),t=e.all("table"),n=e.all("br"),r;t.size()&&n.size()&&(r=t.item(0).get("sourceIndex"),n.each(function(t){var n=t.get("parentNode"),i=n.get("children"),s=n.all(">br");n.test("div")&&(i.size()>2?t.replace(e.Node.create("<wbr>")):t.get("sourceIndex")>r?s.size()&&t.replace(e.Node.create("<wbr>")):s.size()>1&&t.replace(e.Node.create("<wbr>")))}))},_onContentReady:function(t){if(!this._ready){this._ready=!0;var n=this.getInstance(),r=e.clone(this.get("use"));this.fire("contentready"),t&&(n.config.doc=e.Node.getDOMNode(t.target)),r.push(e.bind(function(){n.EditorSelection&&(n.EditorSelection.DEFAULT_BLOCK_TAG=this.get("defaultblock")),this.get("designMode")&&(e.UA.ie?(n.config.doc.body.contentEditable="true",this._ieSetBodyHeight(),n.on("keyup",e.bind(this._ieSetBodyHeight,this),n.config.doc)):n.config.doc.designMode="on"),this.fire("ready")},this)),n.use.apply(n,r),n.one("doc").get("documentElement").addClass("yui-js-enabled")}},_ieHeightCounter:null,_ieSetBodyHeight:function(t){this._ieHeightCounter||(this._ieHeightCounter=0),this._ieHeightCounter++;var n=!1,r,i,s;t||(n=!0);if(t){switch(t.keyCode){case 8:case 13:n=!0}if(t.ctrlKey||t.shiftKey)n=!0}if(n)try{r=this.getInstance(),i=this._iframe.get("offsetHeight"),s=r.config.doc.body.scrollHeight,i>s?(i=i-15+"px",r.config.doc.body.style.height=i):r.config.doc.body.style.height="auto"}catch(t){this._ieHeightCounter<100&&e.later(200,this,this._ieSetBodyHeight)}},_resolveBaseHref:function(t){if(!t||t==="")t=e.config.doc.location.href,t.indexOf("?")!==-1&&(t=t.substring(0,t.indexOf("?"))),t=t.substring(0,t.lastIndexOf("/"))+"/";return t},_getHTML:function(e){if(this._ready){var t=this.getInstance();e=t.one("body").get("innerHTML")}return e},_setHTML:function(t){if(this._ready){var n=this.getInstance();n.one("body").set("innerHTML",t)}else this.on("contentready",e.bind(function(e){var t=this.getInstance();t.one("body").set("innerHTML",e)},this,t));return t},_getLinkedCSS:function(t){e.Lang.isArray(t)||(t=[t]);var n="";return this._ready?n=t:e.each(t,function(e){e!==""&&(n+='<link rel="stylesheet" href="'+e+'" type="text/css">')}),n},_setLinkedCSS:function(e){if(this._ready){var t=this.getInstance();t.Get.css(e)}return e},_setExtraCSS:function(e){if(this._ready){var t=this.getInstance(),n=t.one("#extra_css");n.remove(),t.one("head").append('<style id="extra_css">'+e+"</style>")}return e},_instanceLoaded:function(t){this._instance=t,this._onContentReady();var n=this._instance.config.doc;if(this.get("designMode")&&!e.UA.ie)try{n.execCommand("styleWithCSS",!1,!1),n.execCommand("insertbronreturn",!1,!1)}catch(r){}},use:function(){var t=this.getInstance(),n=e.Array(arguments),r=!1;e.Lang.isFunction(n[n.length-1])&&(r=n.pop()),r&&n.push(function(){r.apply(t,arguments)}),t.__use.apply(t,n)},delegate:function(e,t,n,r){var i=this.getInstance();return i?(r||(r=n,n="body"),i.delegate(e,t,n,r)):!1},getInstance:function(){return this._instance},render:function(t){return this._rendered?this:(this._rendered=!0,t&&this.set("container",t),this._create(e.bind(function(t){var n,r,i=e.bind(function(e){this._instanceLoaded(e)},this),s=e.clone(this.get("use")),o={debug:!1,win:t.win,doc:t.doc},u=e.bind(function(){o=this._resolveWinDoc(o),n=YUI(o),n.host=this.get("host");try{n.use("node-base",i),r&&clearInterval(r)}catch(e){r=setInterval(function(){u()},350)}},this);s.push(u),e.use.apply(e,s)},this)),this)},_handleFocus:function(){var e=this.getInstance(),t=new e.EditorSelection,n,r,i,s;t.anchorNode&&(n=t.anchorNode,n.test("p")&&n.get("innerHTML")===""&&(n=n.get("parentNode")),r=n.get("childNodes"),r.size()&&(r.item(0).test("br")?t.selectNode(n,!0,!1):r.item(0).test("p")?(n=r.item(0).one("br.yui-cursor"),n&&(n=n.get("parentNode")),n||(n=r.item(0).get("firstChild")),n||(n=r.item(0)),n&&t.selectNode(n,!0,!1)):(i=e.one("br.yui-cursor"),i&&(s=i.get("parentNode"),s&&t.selectNode(s,!0,!1)))))},focus:function(t){if(e.UA.ie&&e.UA.ie<9){try{e.one("win").focus(),this.getInstance()&&this.getInstance().one("win")&&this.getInstance().one("win").focus()}catch(n){}t===!0&&this._handleFocus(),e.Lang.isFunction(t)&&t()}else try{e.one("win").focus(),e.later(100,this,function(){this.getInstance()&&this.getInstance().one("win")&&this.getInstance().one("win").focus(),t===!0&&this._handleFocus(),e.Lang.isFunction(t)&&t()})}catch(r){}return this},show:function(){this._iframe.setStyles({position:"static",left:""});if(e.UA.gecko){try{this.getInstance()&&(this.getInstance().config.doc.designMode="on")}catch(t){}this.focus()}return this},hide:function(){return this._iframe.setStyles({position:"absolute",left:"-999999px"}),this}},{THROTTLE_TIME:100,DOM_EVENTS:{dblclick:1,click:1,paste:1,mouseup:1,mousedown:1,keyup:1,keydown:1,keypress:1,activate:1,deactivate:1,beforedeactivate:1,focusin:1,focusout:1},DEFAULT_CSS:"body { background-color: #fff; font: 13px/1.22 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small; } a, a:visited, a:hover { color: blue !important; text-decoration: underline !important; cursor: text !important; } img { cursor: pointer !important; border: none; }",IFRAME_ATTRS:{border:"0",frameBorder:"0",marginWidth:"0",marginHeight:"0",leftMargin:"0",topMargin:"0",allowTransparency:"true",width:"100%",height:"99%"},PAGE_HTML:'<html dir="{DIR}" lang="{LANG}"><head><title>{TITLE}</title>{META}<base href="{BASE_HREF}"/>{LINKED_CSS}<style id="editor_css">{DEFAULT_CSS}</style>{EXTRA_CSS}</head><body>{CONTENT}</body></html>',getDocType:function(){var t=e.config.doc.doctype,r=n.DOC_TYPE;return t?r="<!DOCTYPE "+t.name+(t.publicId?" "+t.publicId:"")+(t.systemId?" "+t.systemId:"")+">":e.config.doc.all&&(t=e.config.doc.all[0],t.nodeType&&t.nodeType===8&&t.nodeValue&&t.nodeValue.toLowerCase().indexOf("doctype")!==-1&&(r="<!"+t.nodeValue+">")),r},DOC_TYPE:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',META:'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=7">',NAME:"frame",ATTRS:{title:{value:"Blank Page"},dir:{value:"ltr"},lang:{value:"en-US"},src:{value:"javascript"+(e.UA.ie?":false":":")+";"},designMode:{writeOnce:!0,value:!1},content:{value:"<br>",setter:"_setHTML",getter:"_getHTML"},basehref:{value:!1,getter:"_resolveBaseHref"},use:{writeOnce:!0,value:["node","node-style","selector-css3"]},container:{value:"body",setter:function(t){return e.one(t)}},node:{readOnly:!0,value:null,getter:function(){return this._iframe}},id:{writeOnce:!0,getter:function(t){return t||(t="iframe-"+e.guid()),t}},linkedcss:{value:"",getter:"_getLinkedCSS",setter:"_setLinkedCSS"},extracss:{value:"",setter:"_setExtraCSS"},host:{value:!1},defaultblock:{value:"p"}}}),e.Frame=n},"3.7.3",{requires:["base","node","selector-css3","yui-throttle"]});
diff --git a/js/yui3/gallery-datatable-paginator/gallery-datatable-paginator-min.js b/js/yui3/gallery-datatable-paginator/gallery-datatable-paginator-min.js
new file mode 100644
index 000000000..4e923ce0b
--- /dev/null
+++ b/js/yui3/gallery-datatable-paginator/gallery-datatable-paginator-min.js
@@ -0,0 +1,2 @@
+YUI.add("gallery-paginator-view",function(a){a.PaginatorModel=a.Base.create("paginatorModel",a.Model,[],{_npages:null,_subscr:null,initializer:function(){this._recalcPagnParams();this._subscr=[];this._subscr.push(this.after("totalItemsChange",this._recalcPagnParams));this._subscr.push(this.after("itemsPerPageChange",this._recalcPagnParams));this._subscr.push(this.on("pageChange",this._changePage));return this;},destructor:function(){a.Array.each(this._subscr,function(b){b.detach();});this._subscr=null;},_changePage:function(d){var b=d.newVal,c=true;if(b<1||!this.get("totalPages")||!this.get("itemsPerPage")){c=false;}if(this.get("totalPages")&&b>this.get("totalPages")){c=false;}if(c){this.set("lastPage",d.prevVal);}else{d.preventDefault();}},_recalcPagnParams:function(){var c=this.get("itemsPerPage"),b=this.get("totalItems");if(b&&c&&b>0&&c>0){np=Math.floor(b/c);if(b%c>0){np++;}this._npages=np;this.set("page",1);return true;}return false;},_getItemIndexStart:function(){return(this.get("page")-1)*this.get("itemsPerPage");},_getItemIndexEnd:function(){var b=this.get("totalItems"),c=this.get("itemIndexStart")+this.get("itemsPerPage");return(c>b)?b:c;}},{ATTRS:{totalItems:{value:null,validator:a.Lang.isNumber},itemsPerPage:{value:null,validator:a.Lang.isNumber},page:{value:1,validator:a.Lang.isNumber},lastPage:{value:null,validator:a.Lang.isNumber},totalPages:{value:null,validator:a.Lang.isNumber,getter:function(){return this._npages;}},itemIndexStart:{value:null,validator:a.Lang.isNumber,getter:"_getItemIndexStart"},itemIndexEnd:{value:null,validator:a.Lang.isNumber,getter:"_getItemIndexEnd"}}});a.PaginatorView=a.Base.create("paginatorView",a.View,[],{TMPL_PAGINATOR:'<a href="#" data-pglink="first" class="{pageLinkClass}" title="First Page">First</a> | '+'<a href="#" data-pglink="prev" class="{pageLinkClass}" title="Prior Page">Prev</a> | '+"{pageLinks}"+' | <a href="#" data-pglink="next" class="{pageLinkClass}" title="Next Page">Next</a> | '+'<a href="#" data-pglink="last" class="{pageLinkClass}" title="Last Page">Last</a>',TMPL_LINK:'<a href="#" data-pglink="{page}" class="{pageLinkClass}" title="Page {page}">{page}</a>',TMPL_basic:"{firstPage} {prevPage} {pageLinks} {nextPage} {lastPage}",TMPL_pglinks:"{pageLinks}",TMPL_selectRPP:'<select class="{selectRPPClass}"></select>',TMPL_selectPage:'<select class="{selectPageClass}"></select>',TMPL_inputRPP:'<input type="text" class="{inputRPPClass}" value="{itemsPerPage}"/>',TMPL_inputPage:'<input type="text" class="{inputPageClass}" value="{page}"/>',model:null,_pagHTML:null,_cssPre:"yui3-pagview",_classContainer:null,_classLinkPage:null,_classLinkPageList:null,_classLinkPageActive:null,_classSelectRPP:null,_classSelectPage:null,_classInputRPP:null,_classInputPage:null,_subscr:null,_myClassName:function(){if(arguments&&arguments.length>0){var c=this._cssPre;for(var b=0;b<arguments.length;b++){c+="-"+arguments[b];}return c;}return"";},initializer:function(){this._classContainer=this._myClassName("container");this._classLinkPage=this._myClassName("link","page");this._classLinkPageList=this._myClassName("link","page","list");this._classLinkPageActive=this._myClassName("link","page","active");this._classInputPage=this._myClassName("input","page");this._classSelectPage=this._myClassName("select","page");this._classSelectRPP=this._myClassName("select","rowsperpage");this._classInputRPP=this._myClassName("input","rowsperpage");var b=this.get("container");if(a.Lang.isString(b)&&c[0]==="#"){this.set("container",a.one(b));}b=this.get("container");if(b instanceof a.Node&&b.getHTML()){this._pagHTML=b.getHTML();}else{if(b instanceof a.Node&&this.get("paginatorTemplate")){var c=this.get("paginatorTemplate");if(c&&c[0]==="#"){this._pagHTML=a.one(c).getHTML();}else{if(c){this._pagHTML=c;}}}}this._bindUI();return this;},_bindUI:function(){var b=this.get("container");this._subscr=[];if(this.get("model")){this.model=this.get("model");this._subscr.push(this.model.after("pageChange",a.bind(this._modelPageChange,this)));this._subscr.push(this.model.after("itemsPerPageChange",a.bind(this._modelStateChange,this)));this._subscr.push(this.model.after("totalItemsChange",a.bind(this._modelStateChange,this)));}this._subscr.push(this.after("render",a.bind(this._updateRPPSelect,this)));this._subscr.push(b.delegate("click",this._clickChangePage,"."+this._classLinkPage,this));this._subscr.push(b.delegate("change",this._selectChangeRowOptions,"."+this._classSelectRPP,this));this._subscr.push(b.delegate("change",this._inputChangePage,"."+this._classInputPage,this));this._subscr.push(b.delegate("change",this._selectChangeRowOptions,"."+this._classInputRPP,this));this._subscr.push(this.after(["render","pageChange"],this.resizePaginator));return this;},destructor:function(){a.Array.each(this._subscr,function(b){b.detach();});this._subscr=null;},render:function(){var o=this.get("container"),j=this.get("model"),h=j.get("totalItems"),l=j.get("itemsPerPage"),d=j.get("totalPages"),b=j.get("page")||1;if(!h||!l||!o){return this;}var c="",e=this.get("pageLinkTemplate"),m=0,f=0;if(this._pagHTML.search(/{pageLinks}/)!==-1){for(var g=0;g<d;g++){plClass=this._classLinkPage+" "+this._classLinkPageList;if(g+1===b){plClass+=" "+this._classLinkPageActive;}m=g*l+1,f=m+l-1;if(f>=h){f=h;}c+=a.Lang.sub(e,{page:(g+1),pageLinkClass:plClass||"",pageStartIndex:m,pageEndIndex:f});}}var k=this._pagHTML;o.setStyle("visibility","hidden");o.setHTML("");k='<div class="{pagClass}" tabindex="-1">'+k+"</div>";var n=a.substitute(k,a.mix({pageLinks:c||"",pageLinkClass:this._classLinkPage,pagClass:this._classContainer,selectRowsPerPage:this.TMPL_selectRPP||"",selectPage:this.TMPL_selectPage||"",inputPage:this.TMPL_inputPage||"",inputRowsPerPage:this.TMPL_inputRPP||"",selectRPPClass:this._classSelectRPP,selectPageClass:this._classSelectPage,inputRPPClass:this._classInputRPP,inputPageClass:this._classInputPage},j.getAttrs()),null,true);o.append(n);o.setStyle("visibility","");this._processPageChange(b);this.fire("render");
+return this;},_processPageChange:function(b){var g=this.get("model"),c=g.get("totalPages"),f=g.get("lastPage"),e=this.get("maxPageLinks"),m=this.get("container"),j=this.get("linkListOffset"),k=m.all("."+this._classLinkPageList);if(k&&this.get("linkHighLight")){var i=(k&&(b-1)<k.size())?k.item(b-1):null;if(i){i.addClass(this._classLinkPageActive);}if(f&&f!==b){i=(k&&(f-1)<k.size())?k.item(f-1):null;if(i){i.removeClass(this._classLinkPageActive);}}}if(m.one("."+this._classInputPage)){m.one("."+this._classInputPage).set("value",b);}if(m.one("."+this._classInputRPP)){m.one("."+this._classInputRPP).set("value",g.get("itemsPerPage"));}if(b===1&&!this.get("circular")){this._disablePageSelector(["first","prev"]);this._disablePageSelector(["last","next"],true);}else{if(b===c&&!this.get("circular")){this._disablePageSelector(["first","prev"],true);this._disablePageSelector(["last","next"]);}else{this._disablePageSelector(["first","prev","last","next"],true);}}this.fire("pageChange",{state:g.getAttrs()});if(c<=e||!k||(k&&k.size()==0)){return;}var h=a.Node.create('<span class="'+this._myClassName("more")+'">'+this.get("pageLinkFiller")+"</span>"),d=a.Node.create('<span class="'+this._myClassName("more")+'">'+this.get("pageLinkFiller")+"</span>");m.all("."+this._myClassName("more")).remove();var l=this._calcOffset(b,j);k.each(function(o,n){if(n==0&&this.get("alwaysShowFirst")||n==c-1&&this.get("alwaysShowLast")){return true;}if(n+1<l.left||n+1>l.right){o.addClass(this._myClassName("hide"));}else{o.removeClass(this._myClassName("hide"));}},this);if(l.left-j>0){k.item(l.left-1).insert(h,"before");}if(l.right+j<=c){k.item(l.right-1).insert(d,"after");}return true;},_calcOffset:function(d,f){var c=this.get("model").get("totalPages"),b=(d-f<1)?1:(d-f),e=(d+f>c)?c:(d+f);return{left:b,right:e};},_disablePageSelector:function(b,e){b=(!a.Lang.isArray(b))?[b]:b;e=(e)?e:false;var d='[data-{suffix}="{sdata}"]',c=this.get("container");a.Array.each(b,function(g){var f=c.one(a.Lang.sub(d,{suffix:"pglink",sdata:g}));if(f){if(e){f.removeClass(this._myClassName("disabled"));}else{f.addClass(this._myClassName("disabled"));}}},this);},_setModel:function(b){if(!b){return;}this.model=b;return b;},_modelPageChange:function(c){var b=c.newVal;if(b){this._processPageChange(b);}},_modelStateChange:function(c){var b=c.newVal;if(b&&!c.silent){this.render();}},_updateRPPSelect:function(){var g=this.get("container"),c=this.get("model"),f=g.one("."+this._classSelectRPP),e=this.get("pageOptions");if(e&&f){if(a.Lang.isArray(e)){var d=f.getDOMNode().options;d.length=0;a.Array.each(e,function(h){var i=new Option(h);d[d.length]=i;});}}if(f){var b=(c&&c.get("itemsPerPage")===c.get("totalItems"))?true:false;var d=f.get("options");d.each(function(h){if(h.get("value")==c.get("itemsPerPage")||(h.get("value").search(/all/i)!==-1&&b)){h.set("selected",true);}},this);}if(g.one("."+this._classSelectPage)){this._updatePageSelect();}},_updatePageSelect:function(){var d=this.get("container"),b=this.get("model"),c=d.one("."+this._classSelectPage);},_inputChangePage:function(d){var b=d.target,f=+b.get("value")||1,c=this.get("model");if(f<1||f>c.get("totalPages")){f=1;b.set("value",f);}c.set("page",f);},_clickChangePage:function(h){var b=h.target,c=this.get("model");h.preventDefault();if(h.target.hasClass(this._myClassName("disabled"))||h.currentTarget.hasClass(this._myClassName("disabled"))){return;}var g=b.getData("pglink")||h.currentTarget.getData("pglink"),f=c.get("totalPages"),d=c.get("page");if(d&&d===g){return;}switch(g){case"first":g=1;break;case"last":g=f;break;case"prev":g=(!d)?1:(d===1)?f:d-1;break;case"next":g=(!d)?1:(d===f)?1:d+1;break;default:g=+g;}c.set("page",g);},_selectChangeRowOptions:function(c){var b=c.target,d=+b.get("value")||b.get("value");if(a.Lang.isString(d)&&d.toLowerCase()==="all"){d=this.get("model").get("totalItems");}this.get("model").set("itemsPerPage",d);this.render();}},{ATTRS:{model:{value:null,setter:"_setModel"},container:{value:null},pageOptions:{value:[10,20,"All"],validator:a.Lang.isArray},paginatorTemplate:{valueFn:function(){return this.TMPL_PAGINATOR;}},pageLinkTemplate:{valueFn:function(){return this.TMPL_LINK;}},linkHighLight:{value:true,validator:a.Lang.isBoolean},maxPageLinks:{value:9999,validator:a.Lang.isNumber},linkListOffset:{value:1,validator:a.Lang.isNumber},pageLinkFiller:{value:"...",validator:a.Lang.isString},alwaysShowFirst:{value:false,validator:a.Lang.isBoolean},alwaysShowLast:{value:false,validator:a.Lang.isBoolean},selectPageFormat:{value:"Page {page}",validator:a.Lang.isString},circular:{value:false,validator:a.Lang.isBoolean}}});},"gallery-2012.08.29-20-10",{skinnable:true,requires:["base-build","model","view","substitute"]});YUI.add("gallery-datatable-paginator",function(b){function a(){}a.ATTRS={paginator:{value:null,setter:"_setPaginator"},serverPaginationMap:{valueFn:"_defPagMap",setter:"_setPagMap",validator:b.Lang.isObject},paginationState:{valueFn:"_defPagState",setter:"_setPagState",getter:"_getPagState"},requestStringTemplate:{value:"",validator:b.Lang.isString},paginatorResize:{value:false,validator:b.Lang.isBoolean}};b.mix(a.prototype,{_mlistArray:null,_pagDataSrc:null,paginator:null,pagModel:null,initializer:function(){if(this.get("paginator")){this.paginator=this.get("paginator");this._eventHandles.paginator=[];this._eventHandles.paginator.push(this.data.after("response",this._afterMLResponse,this));if(this.paginator.get("model")){this.pagModel=this.get("paginator").get("model");this._eventHandles.paginator.push(this.pagModel.after("pageChange",b.bind(this._pageChangeListener,this)));}if(this.get("data")&&this.get("data").size()>0){this._setLocalData();}this._eventHandles.paginator.push(this.data.after(["load","change","add","remove","reset"],b.bind(this._dataChange,this)));this._eventHandles.paginator.push(b.Do.after(this._afterSyncUI,this,"_syncUI",this));this._eventHandles.paginator.push(this.after("renderView",this._notifyRender));}return this;},destructor:function(){b.Array.each(this._eventHandles.paginator,function(c){c.detach();});this._mlistArray=null;this._eventHandles.paginator=null;},processPageRequest:function(m,c){var j=this._mlistArray,o=this.get("paginator"),e=o.get("model"),p=e.get("itemsPerPage");var f,q,g;if(c){f=c.itemIndexStart;q=c.itemIndexEnd||f+p;}else{f=(m-1)*p;q=f+p;q=(q>j.length)?j.length:q;g=q-f+1;}if(this._pagDataSrc!=="local"){var l={},h=this._srvPagMapObj("itemIndexStart"),i=this._srvPagMapObj("totalItems"),d=this._srvPagMapObj("itemsPerPage");l[h]=f;l[d]=p;l["sortBy"]=b.JSON.stringify(this.get("sortBy")||{})||null;l=b.mix(l,this.pagModel.getAttrs(true));l["page"]=this.pagModel.get("page");}switch(this._pagDataSrc){case"ds":var n=this.get("requestStringTemplate")||"";this.datasource.load({request:b.Lang.sub(n,l)});break;case"mlist":case"rest":this.data.load(l);break;default:var k=j.slice(f,q);this.data.reset(k,{silent:true});this.syncUI();}this.resizePaginator();this.fire("pageUpdate",{state:c,view:o});},resizePaginator:function(){if(this.get("paginatorResize")!==true){return;}b.later(25,this,function(){this._syncPaginatorSize();});},dataReset:function(c){if(c instanceof b.ModelList){this._mlistArray=[];c.each(function(d){this._mlistArray.push(d.toJSON());},this);}else{if(b.Lang.isArray(c)){this._mlistArray=[];this._mlistArray=c;}}this.processPageRequest(this.pagModel.get("page"));return this;},_srvPagMapObj:function(f,d){var e=this.get("serverPaginationMap")||{},c=e[f];d=d||"to";if(c&&d=="to"&&c.toServer){c=c.toServer;}if(c&&d!="to"&&c.fromServer){c=c.fromServer;}return c;},_afterSyncUI:function(c){if(!this._pagDataSrc){this._dataChange({});}},_dataChange:function(c){if(this._pagDataSrc){return;}if(!this.datasource&&this.data.url&&!this._pagDataSrc){this._pagDataSrc="mlist";}if(this.datasource&&!this.data.url&&!this._pagDataSrc){this._pagDataSrc="ds";this._eventHandles.paginator.push(this.datasource.get("datasource").after(["*:response","response"],b.bind(this._afterDSResponse,this)));}if(!this._pagDataSrc&&c.models&&b.Lang.isArray(c.models)&&c.models.length>0){c.preventDefault();this._setLocalData(c);}},_setLocalData:function(){var c=this.get("data");this._pagDataSrc="local";this._mlistArray=[];c.each(function(d){this._mlistArray.push(d.toJSON());},this);this.pagModel.set("totalItems",c.size());this.processPageRequest(this.pagModel.get("page"));},_afterDSResponse:function(d){var f=d.response,c=this.get("serverPaginationMap")["totalItems"]||null;if(f.results&&f.results.length>0){if(c&&f.meta&&f.meta[c]&&f.meta[c]>0){this.pagModel.set("totalItems",f.meta[c]);}}this.resizePaginator();},_afterMLResponse:function(d){var c=this.get("serverPaginationMap")["totalItems"]||null;if(d.results&&d.results.length>0){if(c&&d.meta&&d.meta[c]&&d.meta[c]>0){this.pagModel.set("totalItems",d.meta[c]);}}this.resizePaginator();},_pageChangeListener:function(d){var c=+d.newVal||1;this.processPageRequest(c,this.pagModel.getAttrs(true));},_syncPaginatorSize:function(){var c=this.get("boundingBox").one("table");if(!c){return false;}this.paginator.get("container").setStyle("width",c.getComputedStyle("width"));this.fire("paginatorResize");return true;},_defPagMap:function(){return{totalItems:"totalItems",itemsPerPage:"itemsPerPage",page:"page",itemIndexStart:"itemIndexStart"};},_setPagMap:function(d){var c=this._defPagMap();return b.merge(c,d);},_defPagState:function(){var c={};if(this.get("paginator")&&this.get("paginator").model){c=this.get("paginator").model.getAttrs();c.sortBy=this.get("sortBy");}return c;},_getPagState:function(){var c=(this.pagModel)?this.pagModel.getAttrs(true):{};delete c.initialized;c.sortBy=this.get("sortBy");return c;},_setPagState:function(c){if(c.initialized!==undefined){delete c.initialized;}if(c.sortBy!==undefined){this.set("sortBy",c.sortBy);}if(this.pagModel){this.pagModel.setAttrs(c);}return c;},_setPaginator:function(c){if(!c){return;}this.paginator=c;this.initializer();return c;},_notifyRender:function(){if(this.get("paginatorResize")===true){this.resizePaginator();}this.fire("render");}});b.DataTable.Paginator=a;b.Base.mix(b.DataTable,[b.DataTable.Paginator]);},"gallery-2012.09.05-20-01",{requires:["base-build","datatable-base","event-custom"],skinnable:false}); \ No newline at end of file
diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png
new file mode 100644
index 000000000..019c18e14
--- /dev/null
+++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png
Binary files differ
diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css
new file mode 100644
index 000000000..7ea55b74d
--- /dev/null
+++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css
@@ -0,0 +1 @@
+.yui3-skin-sam .yui3-datatable tr.row-expansion td.post-row-expansion{border-top:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable .row-toggle a.row-expand-nub{padding:0 8px;height:14px;margin-left:2px;*display:inline-block}.yui3-skin-sam .yui3-datatable .row-closed a.row-expand-nub{background:url(closed.png) no-repeat}.yui3-skin-sam .yui3-datatable .row-open a.row-expand-nub{background:url(open.png) no-repeat}#yui3-css-stamp.skin-sam-gallery-datatable-row-expansion{display:none}
diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png
new file mode 100644
index 000000000..dc7805017
--- /dev/null
+++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png
Binary files differ
diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js b/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js
new file mode 100644
index 000000000..e3f87804c
--- /dev/null
+++ b/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js
@@ -0,0 +1,383 @@
+YUI.add('gallery-datatable-row-expansion-bmo', function (Y, NAME) {
+
+"use strict";
+
+/**
+ * @module gallery-datatable-row-expansion
+ */
+
+/**********************************************************************
+ * <p>Plugin for DataTable to show additional information for each row via
+ * a twistdown. The result of the template is displayed spanning all the
+ * columns beyond the twistdown column.</p>
+ *
+ * <p>This class patches `getCell` and `getRow` to ignore the additional
+ * rows created by this plugin.</p>
+ *
+ * @main gallery-datatable-row-expansion
+ * @class DataTableRowExpansion
+ * @namespace Plugin
+ * @extends Plugin.Base
+ * @constructor
+ * @param config {Object} configuration
+ */
+function RowExpansion(
+ /* object */ config)
+{
+ RowExpansion.superclass.constructor.call(this, config);
+}
+
+RowExpansion.NAME = "DataTableRowExpansionPlugin";
+RowExpansion.NS = "rowexpander";
+
+RowExpansion.ATTRS =
+{
+ /**
+ * String template or function that returns a string.
+ *
+ * @attribute template
+ * @type {String|Function}
+ * @required
+ */
+ template:
+ {
+ value: '',
+ validator: function(value)
+ {
+ return (Y.Lang.isString(value) || Y.Lang.isFunction(value));
+ }
+ },
+
+ /**
+ * Id of a column (usually not displayed) that yields a
+ * unique value for each record. Used to maintain the twistdown state
+ * when paginating.
+ *
+ * @attribute uniqueIdKey
+ * @type {String}
+ * @required
+ */
+ uniqueIdKey:
+ {
+ value: '',
+ validator: Y.Lang.isString
+ }
+};
+
+/**
+ * The key used to indicate which column contains the twistdown.
+ *
+ * @property Y.RowExpansion.column_key
+ * @type {String}
+ * @value "row-expander"
+ */
+RowExpansion.column_key = 'row-expander';
+
+/**
+ * The class added to rows created by this plugin.
+ *
+ * @property Y.RowExpansion.row_class
+ * @type {String}
+ * @value "row-expansion"
+ */
+RowExpansion.row_class = 'row-expansion';
+
+function insertRow(o)
+{
+ var plugin = this.rowexpander;
+
+ var pre_cells = '';
+ for (var i=0; i<=plugin.col_count.pre; i++)
+ {
+ pre_cells += '<td class="yui3-datatable-cell pre-row-expansion">&nbsp;</td>';
+ }
+
+ var tmpl = plugin.get('template');
+ if (Y.Lang.isFunction(tmpl))
+ {
+ var s = tmpl.call(this, o.data);
+ }
+ else
+ {
+ var s = Y.Lang.sub(tmpl, o.data);
+ }
+
+ var row = o.cell.ancestor();
+ var extra_row = Y.Lang.sub(
+ '<tr class="{c}">' +
+ '{pre}' +
+ '<td colspan="{post}" class="yui3-datatable-cell post-row-expansion">{tmpl}</td>' +
+ '</tr>',
+ {
+ c: row.get('className') + ' ' + RowExpansion.row_class,
+ pre: pre_cells,
+ post: plugin.col_count.post,
+ tmpl: s
+ });
+
+ row.insert(extra_row, 'after');
+}
+
+function formatTwistdown(o)
+{
+ var plugin = this.rowexpander,
+ row_id = o.data[ plugin.get('uniqueIdKey') ],
+ open = plugin.open_rows[ row_id ];
+
+ o.td.addClass('row-toggle');
+ o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed');
+
+ o.td.on('click', function()
+ {
+ var open = plugin.open_rows[ row_id ] = ! plugin.open_rows[ row_id ];
+
+ if (open)
+ {
+ insertRow.call(this, o);
+ o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed');
+ }
+ else
+ {
+ o.cell.ancestor().next().remove();
+ o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed');
+ }
+ },
+ this);
+
+ o.cell.set('innerHTML', '<a class="row-expand-nub" href="javascript:void(0);"></a>');
+
+ if (open)
+ {
+ insertRow.call(this, o);
+ }
+}
+
+function analyzeColumns()
+{
+ function countColumns(result, col)
+ {
+ if (col.key == RowExpansion.column_key)
+ {
+ col.nodeFormatter = formatTwistdown;
+ result.found = true;
+ }
+ else if (col.children)
+ {
+ result = Y.reduce(col.children, result, countColumns);
+ }
+ else
+ {
+ result[ result.found ? 'post' : 'pre' ]++;
+ }
+ return result;
+ }
+
+ this.col_count = Y.reduce(
+ this.get('host').get('columns'),
+ { pre:0, post:0, found:false },
+ countColumns);
+}
+
+var shift_map =
+{
+ above: [-1, 0],
+ below: [ 1, 0],
+ next: [ 0, 1],
+ prev: [ 0, -1],
+ previous: [ 0, -1]
+};
+
+/*
+Returns the `<td>` Node from the given row and column index. Alternately,
+the `seed` can be a Node. If so, the nearest ancestor cell is returned.
+If the `seed` is a cell, it is returned. If there is no cell at the given
+coordinates, `null` is returned.
+
+Optionally, include an offset array or string to return a cell near the
+cell identified by the `seed`. The offset can be an array containing the
+number of rows to shift followed by the number of columns to shift, or one
+of "above", "below", "next", or "previous".
+
+<pre><code>// Previous cell in the previous row
+var cell = table.getCell(e.target, [-1, -1]);
+
+// Next cell
+var cell = table.getCell(e.target, 'next');
+var cell = table.getCell(e.taregt, [0, 1];</pre></code>
+
+@method getCell
+@param {Number[]|Node} seed Array of row and column indexes, or a Node that
+ is either the cell itself or a descendant of one.
+@param {Number[]|String} [shift] Offset by which to identify the returned
+ cell Node
+@return {Node}
+@since 3.5.0
+*/
+function getCell(seed, shift)
+{
+ var tbody = this.tbodyNode,
+ row, cell;
+
+ if (seed && tbody)
+ {
+ if (Y.Lang.isString(shift))
+ {
+ if (shift_map[shift])
+ {
+ shift = shift_map[shift];
+ }
+ else
+ {
+ throw Error('unknown shift in getCell: ' + shift);
+ }
+ }
+
+ if (Y.Lang.isArray(seed))
+ {
+ row = tbody.get('children').item(0);
+ cell = row && row.get('children').item(seed[1]);
+ if (shift)
+ {
+ shift[0] += seed[0];
+ }
+ else
+ {
+ shift = [ seed[0], 0 ];
+ }
+ }
+ else if (seed._node)
+ {
+ cell = seed.ancestor('.' + this.getClassName('cell'), true);
+ if (cell.ancestor('tr.' + RowExpansion.row_class))
+ {
+ throw Error('getCell cannot be called with an element from an expansion row');
+ }
+ }
+
+ if (cell && shift)
+ {
+ var firstRowIndex = tbody.get('firstChild.rowIndex');
+ if (Y.Lang.isArray(shift))
+ {
+ row = cell.ancestor();
+ var delta = Math.sign(shift[0]);
+ if (delta !== 0)
+ {
+ var rows = tbody.get('children');
+ var index = row.get('rowIndex') - firstRowIndex;
+ var count = Math.abs(shift[0]);
+ for (var i=0; i<count && row; i++)
+ {
+ index += delta;
+ row = rows.item(index);
+ if (row && row.hasClass(RowExpansion.row_class))
+ {
+ index += delta;
+ row = rows.item(index);
+ }
+ }
+ }
+
+ index = cell.get('cellIndex') + shift[1];
+ cell = row && row.get('children').item(index);
+ }
+ }
+ }
+
+ return (cell || null);
+}
+
+/*
+Returns the `<tr>` Node from the given row index, Model, or Model's
+`clientId`. If the rows haven't been rendered yet, or if the row can't be
+found by the input, `null` is returned.
+
+@method getRow
+@param {Number|String|Model} id Row index, Model instance, or clientId
+@return {Node}
+@since 3.5.0
+*/
+function getRow(id)
+{
+ var tbody = this.tbodyNode,
+ row = null;
+
+ if (tbody)
+ {
+ if (id)
+ {
+ id = this._idMap[id.get ? id.get('clientId') : id] || id;
+ }
+
+ row = Y.one(Y.Lang.isNumber(id) ? this.getCell([id,0]).ancestor() : '#' + id);
+ }
+
+ return row;
+}
+
+function replaceGetters()
+{
+ var view = this.get('host').view;
+ if (view instanceof Y.DataTable.TableView &&
+ view.body instanceof Y.DataTable.BodyView)
+ {
+ var body = view.body;
+
+ this.orig_getCell = body.getCell;
+ this.orig_getRow = body.getRow;
+
+ body.getCell = getCell;
+ body.getRow = getRow;
+ }
+}
+
+function restoreGetters()
+{
+ var view = this.get('host').view;
+ if (view.body && this.orig_getCell)
+ {
+ view.body.getCell = this.orig_getCell;
+ }
+
+ if (view.body && this.orig_getRow)
+ {
+ view.body.getRow = this.orig_getRow;
+ }
+}
+
+Y.extend(RowExpansion, Y.Plugin.Base,
+{
+ initializer: function(config)
+ {
+ this.open_rows = {};
+ this.on('uniqueIdKeyChange', function()
+ {
+ this.open_rows = {};
+ });
+
+ analyzeColumns.call(this);
+ this.afterHostEvent('columnsChange', analyzeColumns);
+
+ this.afterHostEvent('table:renderTable', replaceGetters);
+ },
+
+ destructor: function()
+ {
+ restoreGetters.call(this);
+ }
+});
+
+Y.namespace("Plugin");
+Y.Plugin.DataTableRowExpansion = RowExpansion;
+
+
+}, '@VERSION@', {
+ "skinnable": "true",
+ "requires": [
+ "datatable",
+ "plugin",
+ "gallery-funcprog",
+ "gallery-node-optimizations",
+ "gallery-math"
+ ]
+});
diff --git a/js/yui3/gallery-funcprog/gallery-funcprog-min.js b/js/yui3/gallery-funcprog/gallery-funcprog-min.js
new file mode 100644
index 000000000..5354b068c
--- /dev/null
+++ b/js/yui3/gallery-funcprog/gallery-funcprog-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-funcprog",function(e,t){"use strict";function n(t,n){var r=e.Array(arguments,1,!0);switch(e.Array.test(n)){case 1:return e.Array[t].apply(null,r);case 2:return r[0]=e.Array(n,0,!0),e.Array[t].apply(null,r);default:return n&&n[t]&&n!==e?(r.shift(),n[t].apply(n,r)):e.Object[t].apply(null,r)}}e.mix(e,{every:function(e,t,r,i){return n("every",e,t,r,i)},filter:function(e,t,r,i){return n("filter",e,t,r,i)},find:function(e,t,r,i){return n("find",e,t,r,i)},map:function(e,t,r,i){return n("map",e,t,r,i)},partition:function(e,t,r,i){return n("partition",e,t,r,i)},reduce:function(e,t,r,i,s){return n("reduce",e,t,r,i,s)},reduceRight:function(e,t,r,i,s){return n("reduceRight",e,t,r,i,s)},reject:function(e,t,r,i){return n("reject",e,t,r,i)}}),e.mix(e.Array,{findIndexOf:function(t,n,r){var i=-1;return e.Array.some(t,function(e,s){if(n.call(r,e,s,t))return i=s,!0}),i}}),e.Array.reduceRight=e.Lang._isNative(Array.prototype.reduceRight)?function(e,t,n,r){return Array.prototype.reduceRight.call(e,function(e,t,i,s){return n.call(r,e,t,i,s)},t)}:function(e,t,n,r){var i=t;for(var s=e.length-1;s>=0;s--)i=n.call(r,i,e[s],s,e);return i}},"@VERSION@",{requires:["oop","array-extras","gallery-object-extras"],optional:["gallery-nodelist-extras2"]});
diff --git a/js/yui3/gallery-math/gallery-math-min.js b/js/yui3/gallery-math/gallery-math-min.js
new file mode 100644
index 000000000..1d9348e48
--- /dev/null
+++ b/js/yui3/gallery-math/gallery-math-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-math",function(e,t){"use strict";e.mix(Math,{sign:function(e){return e<0?-1:e>0?1:0},add:function(){return e.Array.reduce(e.Array(arguments),0,function(t,n){return e.Lang.isArray(n)&&(n=Math.add.apply(this,n)),t+n})},addReciprocals:function(){return e.Array.reduce(e.Array(arguments),0,function(t,n){return e.Lang.isArray(n)?t+Math.addReciprocals.apply(this,n):t+1/n})},parallel:function(){return 1/Math.addReciprocals.apply(this,arguments)},multiply:function(){return e.Array.reduce(e.Array(arguments),1,function(t,n){return e.Lang.isArray(n)&&(n=Math.multiply.apply(this,n)),t*n})},degreesToRadians:function(e){return e*Math.PI/180},radiansToDegrees:function(e){return e*180/Math.PI},acosh:function(e){return Math.log(e+Math.sqrt(e*e-1))},asinh:function(e){return Math.log(e+Math.sqrt(e*e+1))},atanh:function(e){return Math.log((1+e)/(1-e))/2},cosh:function(e){var t=Math.exp(e);return(t+1/t)/2},sinh:function(e){var t=Math.exp(e);return(t-1/t)/2},tanh:function(e){var t=Math.exp(2*e);return(t-1)/(t+1)}})},"@VERSION@",{requires:["array-extras"]});
diff --git a/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js b/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js
new file mode 100644
index 000000000..297b60ac6
--- /dev/null
+++ b/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-node-optimizations",function(e,t){"use strict";var n=/^([a-z]*)\.([-_a-z0-9]+)$/i,r=/^\.([-_a-z0-9]+)$/i,i=/^[a-z]+$/i;e.Node.class_re_prefix="(?:^|\\s)(?:",e.Node.class_re_suffix=")(?:\\s|$)";var s=e.Node.prototype.ancestor;e.Node.prototype.ancestor=function(t,n){if(e.Lang.isString(t)){var o=r.exec(t);if(o&&o.length)return this.getAncestorByClassName(o[1],n);if(i.test(t))return this.getAncestorByTagName(t,n)}return s.apply(this,arguments)},e.Node.prototype.getAncestorByClassName=function(t,n){var r=this._node;n||(r=r.parentNode);while(r&&!e.DOM.hasClass(r,t)){r=r.parentNode;if(!r||!r.tagName)return null}return e.one(r)},e.Node.prototype.getAncestorByTagName=function(t,n){var r=this._node;n||(r=r.parentNode),t=t.toLowerCase();while(r&&r.tagName.toLowerCase()!=t){r=r.parentNode;if(!r||!r.tagName)return null}return e.one(r)},e.Node.prototype.getElementsByClassName=function(t,n){var r=e.Node.getDOMNode(this).getElementsByTagName(n||"*"),i=new e.NodeList;for(var s=0;s<r.length;s++){var o=r[s];e.DOM.hasClass(o,t)&&i.push(o)}return i},e.Node.prototype.getFirstElementByClassName=function(t,n){if(!n||n=="*"||n=="div"){var r=[e.Node.getDOMNode(this)],i=[];while(r.length){for(var s=0;s<r.length;s++){var o=r[s],u=o.children||o.childNodes;for(var a=0;a<u.length;a++){var f=u[a];if(e.DOM.hasClass(f,t))return e.one(f);i.push(f)}}r=i,i=[]}}else{var l=e.Node.getDOMNode(this).getElementsByTagName(n||"*");for(var s=0;s<l.length;s++){var f=l[s];if(e.DOM.hasClass(f,t))return e.one(f)}}return null}},"@VERSION@",{requires:["node-base"]});
diff --git a/js/yui3/gallery-object-extras/gallery-object-extras-min.js b/js/yui3/gallery-object-extras/gallery-object-extras-min.js
new file mode 100644
index 000000000..608ae8f57
--- /dev/null
+++ b/js/yui3/gallery-object-extras/gallery-object-extras-min.js
@@ -0,0 +1 @@
+YUI.add("gallery-object-extras",function(e,t){"use strict";e.mix(e.Object,{every:function(e,t,n,r){for(var i in e)if((r||e.hasOwnProperty(i))&&!t.call(n,e[i],i,e))return!1;return!0},filter:function(e,t,n,r){var i={};for(var s in e){var o=e[s];(r||e.hasOwnProperty(s))&&t.call(n,o,s,e)&&(i[s]=o)}return i},find:function(e,t,n,r){for(var i in e){var s=e[i];if((r||e.hasOwnProperty(i))&&t.call(n,s,i,e))return s}return null},keyOf:function(e,t,n){for(var r in e)if((n||e.hasOwnProperty(r))&&e[r]===t)return r;return null},invoke:function(t,n){var r=e.Array(arguments,2,!0),i={};for(var s in t){var o=t[s];t.hasOwnProperty(s)&&e.Lang.isFunction(o[n])&&(i[s]=o[n].apply(o,r))}return i},map:function(e,t,n,r){var i={};for(var s in e)if(r||e.hasOwnProperty(s))i[s]=t.call(n,e[s],s,e);return i},partition:function(e,t,n,r){var i={matches:{},rejects:{}};for(var s in e){var o=e[s];if(r||e.hasOwnProperty(s)){var u=t.call(n,o,s,e)?i.matches:i.rejects;u[s]=o}}return i},reduce:function(e,t,n,r,i){var s=t;for(var o in e)if(i||e.hasOwnProperty(o))s=n.call(r,s,e[o],o,e);return s},reject:function(t,n,r,i){return e.Object.filter(t,function(e,t,i){return!n.call(r,e,t,i)},r,i)},zip:function(t,n){var r={};return e.Array.each(t,function(e,t){r[e.toString()]=n[t]}),r}}),e.Object.reduceRight=e.Object.reduce,e.mix(e.Array,{toObject:function(t,n){var r={};return e.Array.each(t,function(e){r[e[n]]=e}),r}})},"@VERSION@",{requires:[""],optional:["gallery-funcprog"]});
diff --git a/js/yui3/gallery-paginator-view/assets/skins/sam/gallery-paginator-view.css b/js/yui3/gallery-paginator-view/assets/skins/sam/gallery-paginator-view.css
new file mode 100644
index 000000000..11a371aa4
--- /dev/null
+++ b/js/yui3/gallery-paginator-view/assets/skins/sam/gallery-paginator-view.css
@@ -0,0 +1 @@
+.yui3-pagview-link-page{border:1px solid #b0c4de;padding:5px;text-decoration:none;color:blue}.yui3-pagview-link-page a{width:35px;height:35px;text-align:center;color:#324759;text-decoration:none;border:1px solid #324759;padding:5px;margin-top:5px;margin-right:3px;margin-left:3px;margin-bottom:5px}.yui3-pagview-bar{background:#fff url("http://yui.yahooapis.com/3.6.0/build/assets/skins/sam/sprite.png") repeat-x 0 0;background-image:-webkit-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-moz-linear-gradient(top,transparent 40%,rgba(0,0,0,0.21));background-image:-ms-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:-o-linear-gradient(transparent 40%,rgba(0,0,0,0.21));background-image:linear-gradient(transparent 40%,rgba(0,0,0,0.21));-moz-border-bottom-colors:none;-moz-border-image:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:-moz-use-text-color #cbcbcb -moz-use-text-color -moz-use-text-color;border:1px solid #cbcbcb;vertical-align:middle}.yui3-pagview-link-page-list{width:10px;margin:0 2px 0 2px}.yui3-pagview-container{outline:0}.yui3-pagview-link-page-active{background-color:#90ee90;color:black}.yui3-pagview-disabled{opacity:.2;cursor:default}.yui3-pagview-hide{display:none}.yui3-pagview-input-page{width:15px;height:13px;text-align:center}#yui3-css-stamp.skin-sam-gallery-paginator-view{display:none}
diff --git a/js/yui3/gesture-simulate/gesture-simulate-min.js b/js/yui3/gesture-simulate/gesture-simulate-min.js
new file mode 100644
index 000000000..154324735
--- /dev/null
+++ b/js/yui3/gesture-simulate/gesture-simulate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("gesture-simulate",function(e,t){function T(n){n||e.error(t+": invalid target node"),this.node=n,this.target=e.Node.getDOMNode(n);var r=this.node.getXY(),i=this._getDims();a=r[0]+i[0]/2,f=r[1]+i[1]/2}var t="gesture-simulate",n=e.config.win&&"ontouchstart"in e.config.win&&!e.UA.phantomjs&&!(e.UA.chrome&&e.UA.chrome<6),r={tap:1,doubletap:1,press:1,move:1,flick:1,pinch:1,rotate:1},i={touchstart:1,touchmove:1,touchend:1,touchcancel:1},s=e.config.doc,o,u=20,a,f,l={HOLD_TAP:10,DELAY_TAP:10,HOLD_PRESS:3e3,MIN_HOLD_PRESS:1e3,MAX_HOLD_PRESS:6e4,DISTANCE_MOVE:200,DURATION_MOVE:1e3,MAX_DURATION_MOVE:5e3,MIN_VELOCITY_FLICK:1.3,DISTANCE_FLICK:200,DURATION_FLICK:1e3,MAX_DURATION_FLICK:5e3,DURATION_PINCH:1e3},c="touchstart",h="touchmove",p="touchend",d="gesturestart",v="gesturechange",m="gestureend",g="mouseup",y="mousemove",b="mousedown",w="click",E="dblclick",S="x",x="y";T.prototype={_toRadian:function(e){return e*(Math.PI/180)},_getDims:function(){var e,t,n;return this.target.getBoundingClientRect?(e=this.target.getBoundingClientRect(),"height"in e?n=e.height:n=Math.abs(e.bottom-e.top),"width"in e?t=e.width:t=Math.abs(e.right-e.left)):(e=this.node.get("region"),t=e.width,n=e.height),[t,n]},_calculateDefaultPoint:function(t){var n;return!e.Lang.isArray(t)||t.length===0?t=[a,f]:(t.length==1&&(n=this._getDims[1],t[1]=n/2),t[0]=this.node.getX()+t[0],t[1]=this.node.getY()+t[1]),t},rotate:function(n,r,i,s,o,u,a){var f,l=i,c=s;if(!e.Lang.isNumber(l)||!e.Lang.isNumber(c)||l<0||c<0)f=this.target.offsetWidth<this.target.offsetHeight?this.target.offsetWidth/4:this.target.offsetHeight/4,l=f,c=f;e.Lang.isNumber(a)||e.error(t+"Invalid rotation detected."),this.pinch(n,r,l,c,o,u,a)},pinch:function(n,r,i,s,o,a,f){var g,y,b=u,w,E=0,S=i,x=s,T,N,C,k,L,A,O,M,_,D={start:[],end:[]},P={start:[],end:[]},H,B;r=this._calculateDefaultPoint(r),(!e.Lang.isNumber(S)||!e.Lang.isNumber(x)||S<0||x<0)&&e.error(t+"Invalid startRadius and endRadius detected.");if(!e.Lang.isNumber(o)||o<=0)o=l.DURATION_PINCH;if(!e.Lang.isNumber(a))a=0;else{a%=360;while(a<0)a+=360}e.Lang.isNumber(f)||(f=0),e.AsyncQueue.defaults.timeout=b,g=new e.AsyncQueue,N=r[0],C=r[1],O=a,M=a+f,D.start=[N+S*Math.sin(this._toRadian(O)),C-S*Math.cos(this._toRadian(O))],D.end=[N+x*Math.sin(this._toRadian(M)),C-x*Math.cos(this._toRadian(M))],P.start=[N-S*Math.sin(this._toRadian(O)),C+S*Math.cos(this._toRadian(O))],P.end=[N-x*Math.sin(this._toRadian(M)),C+x*Math.cos(this._toRadian(M))],k=1,L=s/i,g.add({fn:function(){var t,n,r,i;t={pageX:D.start[0],pageY:D.start[1],clientX:D.start[0],clientY:D.start[1]},n={pageX:P.start[0],pageY:P.start[1],clientX:P.start[0],clientY:P.start[1]},i=this._createTouchList([e.merge({identifier:E++},t),e.merge({identifier:E++},n)]),r={pageX:(D.start[0]+P.start[0])/2,pageY:(D.start[0]+P.start[1])/2,clientX:(D.start[0]+P.start[0])/2,clientY:(D.start[0]+P.start[1])/2},this._simulateEvent(this.target,c,e.merge({touches:i,targetTouches:i,changedTouches:i,scale:k,rotation:O},r)),e.UA.ios>=2&&this._simulateEvent(this.target,d,e.merge({scale:k,rotation:O},r))},timeout:0,context:this}),H=Math.floor(o/b),T=(x-S)/H,A=(L-k)/H,_=(M-O)/H,B=function(t){var n=S+T*t,r=N+n*Math.sin(this._toRadian(O+_*t)),i=C-n*Math.cos(this._toRadian(O+_*t)),s=N-n*Math.sin(this._toRadian(O+_*t)),o=C+n*Math.cos(this._toRadian(O+_*t)),u=(r+s)/2,a=(i+o)/2,f,l,c,p;f={pageX:r,pageY:i,clientX:r,clientY:i},l={pageX:s,pageY:o,clientX:s,clientY:o},p=this._createTouchList([e.merge({identifier:E++},f),e.merge({identifier:E++},l)]),c={pageX:u,pageY:a,clientX:u,clientY:a},this._simulateEvent(this.target,h,e.merge({touches:p,targetTouches:p,changedTouches:p,scale:k+A*t,rotation:O+_*t},c)),e.UA.ios>=2&&this._simulateEvent(this.target,v,e.merge({scale:k+A*t,rotation:O+_*t},c))};for(y=0;y<H;y++)g.add({fn:B,args:[y],context:this});g.add({fn:function(){var t=this._getEmptyTouchList(),n,r,i,s;n={pageX:D.end[0],pageY:D.end[1],clientX:D.end[0],clientY:D.end[1]},r={pageX:P.end[0],pageY:P.end[1],clientX:P.end[0],clientY:P.end[1]},s=this._createTouchList([e.merge({identifier:E++},n),e.merge({identifier:E++},r)]),i={pageX:(D.end[0]+P.end[0])/2,pageY:(D.end[0]+P.end[1])/2,clientX:(D.end[0]+P.end[0])/2,clientY:(D.end[0]+P.end[1])/2},e.UA.ios>=2&&this._simulateEvent(this.target,m,e.merge({scale:L,rotation:M},i)),this._simulateEvent(this.target,p,e.merge({touches:t,targetTouches:t,changedTouches:s,scale:L,rotation:M},i))},context:this}),n&&e.Lang.isFunction(n)&&g.add({fn:n,context:this.node}),g.run()},tap:function(t,r,i,s,o){var u=new e.AsyncQueue,a=this._getEmptyTouchList(),f,h,d,v,m;r=this._calculateDefaultPoint(r);if(!e.Lang.isNumber(i)||i<1)i=1;e.Lang.isNumber(s)||(s=l.HOLD_TAP),e.Lang.isNumber(o)||(o=l.DELAY_TAP),h={pageX:r[0],pageY:r[1],clientX:r[0],clientY:r[1]},f=this._createTouchList([e.merge({identifier:0},h)]),v=function(){this._simulateEvent(this.target,c,e.merge({touches:f,targetTouches:f,changedTouches:f},h))},m=function(){this._simulateEvent(this.target,p,e.merge({touches:a,targetTouches:a,changedTouches:f},h))};for(d=0;d<i;d++)u.add({fn:v,context:this,timeout:d===0?0:o}),u.add({fn:m,context:this,timeout:s});i>1&&!n&&u.add({fn:function(){this._simulateEvent(this.target,E,h)},context:this}),t&&e.Lang.isFunction(t)&&u.add({fn:t,context:this.node}),u.run()},flick:function(n,r,i,s,o){var u;r=this._calculateDefaultPoint(r),e.Lang.isString(i)?(i=i.toLowerCase(),i!==S&&i!==x&&e.error(t+"(flick): Only x or y axis allowed")):i=S,e.Lang.isNumber(s)||(s=l.DISTANCE_FLICK),e.Lang.isNumber(o)?o>l.MAX_DURATION_FLICK&&(o=l.MAX_DURATION_FLICK):o=l.DURATION_FLICK,Math.abs(s)/o<l.MIN_VELOCITY_FLICK&&(o=Math.abs(s)/l.MIN_VELOCITY_FLICK),u={start:e.clone(r),end:[i===S?r[0]+s:r[0],i===x?r[1]+s:r[1]]},this._move(n,u,o)},move:function(t,n,r){var i;e.Lang.isObject(n)?(e.Lang.isArray(n.point)?n.point=this._calculateDefaultPoint(n.point):n.point=this._calculateDefaultPoint([]),e.Lang.isNumber(n.xdist)||(n.xdist=l.DISTANCE_MOVE),e.Lang.isNumber(n.ydist)||(n.ydist=0)):n={point:this._calculateDefaultPoint([]),xdist:l.DISTANCE_MOVE,ydist:0},e.Lang.isNumber(r)?r>l.MAX_DURATION_MOVE&&(r=l.MAX_DURATION_MOVE):r=l.DURATION_MOVE,i={start:e.clone(n.point),end:[n.point[0]+n.xdist,n.point[1]+n.ydist]},this._move(t,i,r)},_move:function(t,n,r){var i,s,o=u,d,v,m,g=0,y;e.Lang.isNumber(r)?r>l.MAX_DURATION_MOVE&&(r=l.MAX_DURATION_MOVE):r=l.DURATION_MOVE,e.Lang.isObject(n)?(e.Lang.isArray(n.start)||(n.start=[a,f]),e.Lang.isArray(n.end)||(n.end=[a+l.DISTANCE_MOVE,f])):n={start:[a,f],end:[a+l.DISTANCE_MOVE,f]},e.AsyncQueue.defaults.timeout=o,i=new e.AsyncQueue,i.add({fn:function(){var t={pageX:n.start[0],pageY:n.start[1],clientX:n.start[0],clientY:n.start[1]},r=this._createTouchList([e.merge({identifier:g++},t)]);this._simulateEvent(this.target,c,e.merge({touches:r,targetTouches:r,changedTouches:r},t))},timeout:0,context:this}),d=Math.floor(r/o),v=(n.end[0]-n.start[0])/d,m=(n.end[1]-n.start[1])/d,y=function(t){var r=n.start[0]+v*t,i=n.start[1]+m*t,s={pageX:r,pageY:i,clientX:r,clientY:i},o=this._createTouchList([e.merge({identifier:g++},s)]);this._simulateEvent(this.target,h,e.merge({touches:o,targetTouches:o,changedTouches:o},s))};for(s=0;s<d;s++)i.add({fn:y,args:[s],context:this});i.add({fn:function(){var t={pageX:n.end[0],pageY:n.end[1],clientX:n.end[0],clientY:n.end[1]},r=this._createTouchList([e.merge({identifier:g},t)]);this._simulateEvent(this.target,h,e.merge({touches:r,targetTouches:r,changedTouches:r},t))},timeout:0,context:this}),i.add({fn:function(){var t={pageX:n.end[0],pageY:n.end[1],clientX:n.end[0],clientY:n.end[1]},r=this._getEmptyTouchList(),i=this._createTouchList([e.merge({identifier:g},t)]);this._simulateEvent(this.target,p,e.merge({touches:r,targetTouches:r,changedTouches:i},t))},context:this}),t&&e.Lang.isFunction(t)&&i.add({fn:t,context:this.node}),i.run()},_getEmptyTouchList:function(){return o||(o=this._createTouchList([])),o},_createTouchList:function(n){var r=[],i,o=this;return!!n&&e.Lang.isArray(n)?e.UA.android&&e.UA.android>=4||e.UA.ios&&e.UA.ios>=2?(e.each(n,function(t){t.identifier||(t.identifier=0),t.pageX||(t.pageX=0),t.pageY||(t.pageY=0),t.screenX||(t.screenX=0),t.screenY||(t.screenY=0),r.push(s.createTouch(e.config.win,o.target,t.identifier,t.pageX,t.pageY,t.screenX,t.screenY))}),i=s.createTouchList.apply(s,r)):e.UA.ios&&e.UA.ios<2?e.error(t+": No touch event simulation framework present."):(i=[],e.each(n,function(e){e.identifier||(e.identifier=0),e.clientX||(e.clientX=0),e.clientY||(e.clientY=0),e.pageX||(e.pageX=0),e.pageY||(e.pageY=0),e.screenX||(e.screenX=0),e.screenY||(e.screenY=0),i.push({target:o.target,identifier:e.identifier,clientX:e.clientX,clientY:e.clientY,pageX:e.pageX,pageY:e.pageY,screenX:e.screenX,screenY:e.screenY})}),i.item=function(e){return i[e]}):e.error(t+": Invalid touchPoints passed"),i},_simulateEvent:function(t,r,s){var o;i[r]?n?e.Event.simulate(t,r,s):this._isSingleTouch(s.touches,s.targetTouches,s.changedTouches)?(r={touchstart:b,touchmove:y,touchend:g}[r],s.button=0,s.relatedTarget=null,o=r===g?s.changedTouches:s.touches,s=e.mix(s,{screenX:o.item(0).screenX,screenY:o.item(0).screenY,clientX:o.item(0).clientX,clientY:o.item(0).clientY},!0),e.Event.simulate(t,r,s),r==g&&e.Event.simulate(t,w,s)):e.error("_simulateEvent(): Event '"+r+"' has multi touch objects that can't be simulated in your platform."):e.Event.simulate(t,r,s)},_isSingleTouch:function(e,t,n){return e&&e.length<=1&&t&&t.length<=1&&n&&n.length<=1}},e.GestureSimulation=T,e.GestureSimulation.defaults=l,e.GestureSimulation.GESTURES=r,e.Event.simulateGesture=function(n,i,s,o){n=e.one(n);var u=new e.GestureSimulation(n);i=i.toLowerCase(),!o&&e.Lang.isFunction(s)&&(o=s,s={}),s=s||{};if(r[i])switch(i){case"tap":u.tap(o,s.point,s.times,s.hold,s.delay);break;case"doubletap":u.tap(o,s.point,2);break;case"press":e.Lang.isNumber(s.hold)?s.hold<l.MIN_HOLD_PRESS?s.hold=l.MIN_HOLD_PRESS:s.hold>l.MAX_HOLD_PRESS&&(s.hold=l.MAX_HOLD_PRESS):s.hold=l.HOLD_PRESS,u.tap(o,s.point,1,s.hold);break;case"move":u.move(o,s.path,s.duration);break;case"flick":u.flick(o,s.point,s.axis,s.distance,s.duration);break;case"pinch":u.pinch(o,s.center,s.r1,s.r2,s.duration,s.start,s.rotation);break;case"rotate":u.rotate(o,s.center,s.r1,s.r2,s.duration,s.start,s.rotation)}else e.error(t+": Not a supported gesture simulation: "+i)}},"3.7.3",{requires:["async-queue","event-simulate","node-screen"]});
diff --git a/js/yui3/get-nodejs/get-min.js b/js/yui3/get-nodejs/get-min.js
new file mode 100644
index 000000000..acac34398
--- /dev/null
+++ b/js/yui3/get-nodejs/get-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("get",function(a){var j=require("path"),b=require("vm"),f=require("fs"),e=require("request"),g=f.existsSync||j.existsSync;a.Get=function(){};a.config.base=j.join(__dirname,"../");YUI.require=require;YUI.process=process;var i=function(k){return k.replace(/\\/g,"\\\\");};a.Get._exec=function(q,m,k){var p=i(j.dirname(m));var r=i(m);if(p.match(/^https?:\/\//)){p=".";r="remoteResource";}var n="(function(YUI) { var __dirname = '"+p+"'; "+"var __filename = '"+r+"'; "+"var process = YUI.process;"+"var require = function(file) {"+" if (file.indexOf('./') === 0) {"+" file = __dirname + file.replace('./', '/'); }"+" return YUI.require(file); }; "+q+" ;return YUI; })";var l=b.createScript(n,m);var o=l.runInThisContext(n);YUI=o(YUI);k(null,m);};a.Get._include=function(n,k){var m=this;if(n.match(/^https?:\/\//)){var l={url:n,timeout:m.timeout};e(l,function(r,q,p){if(r){k(r,n);}else{a.Get._exec(p,n,k);}});}else{if(a.config.useSync){if(g(n)){var o=f.readFileSync(n,"utf8");a.Get._exec(o,n,k);}else{k("Path does not exist: "+n,n);}}else{f.readFile(n,"utf8",function(q,p){if(q){k(q,n);}else{a.Get._exec(p,n,k);}});}}};var d=function(l,m,k){if(a.Lang.isFunction(l.onEnd)){l.onEnd.call(a,m,k);}},h=function(k){if(a.Lang.isFunction(k.onSuccess)){k.onSuccess.call(a,k);}d(k,"success","success");},c=function(k,l){l.errors=[l];if(a.Lang.isFunction(k.onFailure)){k.onFailure.call(a,l,k);}d(k,l,"fail");};a.Get.js=function(u,v){var n=a.Array,t=this,r=n(u),k,p,o=r.length,q=0,m=function(){if(q===o){h(v);}};for(p=0;p<o;p++){k=r[p];if(a.Lang.isObject(k)){k=k.url;}k=k.replace(/'/g,"%27");a.Get._include(k,function(s,l){if(!a.config){a.config={debug:true};}if(v.onProgress){v.onProgress.call(v.context||a,l);}if(s){c(v,s);}else{q++;m();}});}};a.Get.script=a.Get.js;a.Get.css=function(l,k){h(k);};},"3.7.3",{requires:["yui-base"]}); \ No newline at end of file
diff --git a/js/yui3/get-nodejs/get-nodejs-min.js b/js/yui3/get-nodejs/get-nodejs-min.js
new file mode 100644
index 000000000..daa56e6b6
--- /dev/null
+++ b/js/yui3/get-nodejs/get-nodejs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("get",function(e,t){var n=require("path"),r=require("vm"),i=require("fs"),s=require("request"),o=i.existsSync||n.existsSync;e.Get=function(){},e.config.base=n.join(__dirname,"../"),YUI.require=require,YUI.process=process;var u=function(e){return e.replace(/\\/g,"\\\\")};e.Get._exec=function(e,t,i){var s=u(n.dirname(t)),o=u(t);s.match(/^https?:\/\//)&&(s=".",o="remoteResource");var a="(function(YUI) { var __dirname = '"+s+"'; "+"var __filename = '"+o+"'; "+"var process = YUI.process;"+"var require = function(file) {"+" if (file.indexOf('./') === 0) {"+" file = __dirname + file.replace('./', '/'); }"+" return YUI.require(file); }; "+e+" ;return YUI; })",f=r.createScript(a,t),l=f.runInThisContext(a);YUI=l(YUI),i(null,t)},e.Get._include=function(t,n){var r=this;if(t.match(/^https?:\/\//)){var u={url:t,timeout:r.timeout};s(u,function(r,i,s){r?n(r,t):e.Get._exec(s,t,n)})}else if(e.config.useSync)if(o(t)){var a=i.readFileSync(t,"utf8");e.Get._exec(a,t,n)}else n("Path does not exist: "+t,t);else i.readFile(t,"utf8",function(r,i){r?n(r,t):e.Get._exec(i,t,n)})};var a=function(t,n,r){e.Lang.isFunction(t.onEnd)&&t.onEnd.call(e,n,r)},f=function(t){e.Lang.isFunction(t.onSuccess)&&t.onSuccess.call(e,t),a(t,"success","success")},l=function(t,n){n.errors=[n],e.Lang.isFunction(t.onFailure)&&t.onFailure.call(e,n,t),a(t,n,"fail")};e.Get.js=function(t,n){var r=e.Array,i=this,s=r(t),o,u,a=s.length,c=0,h=function(){c===a&&f(n)};for(u=0;u<a;u++)o=s[u],e.Lang.isObject(o)&&(o=o.url),o=o.replace(/'/g,"%27"),e.Get._include(o,function(t,r){e.config||(e.config={debug:!0}),n.onProgress&&n.onProgress.call(n.context||e,r),t?l(n,t):(c++,h())})},e.Get.script=e.Get.js,e.Get.css=function(e,t){f(t)}},"3.7.3");
diff --git a/js/yui3/get/get-min.js b/js/yui3/get/get-min.js
new file mode 100644
index 000000000..a67869202
--- /dev/null
+++ b/js/yui3/get/get-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("get",function(e,t){var n=e.Lang,r,i,s;e.Get=i={cssOptions:{attributes:{rel:"stylesheet"},doc:e.config.linkDoc||e.config.doc,pollInterval:50},jsOptions:{autopurge:!0,doc:e.config.scriptDoc||e.config.doc},options:{attributes:{charset:"utf-8"},purgethreshold:20},REGEX_CSS:/\.css(?:[?;].*)?$/i,REGEX_JS:/\.js(?:[?;].*)?$/i,_insertCache:{},_pending:null,_purgeNodes:[],_queue:[],abort:function(e){var t,n,r,i,s;if(!e.abort){n=e,s=this._pending,e=null;if(s&&s.transaction.id===n)e=s.transaction,this._pending=null;else for(t=0,i=this._queue.length;t<i;++t){r=this._queue[t].transaction;if(r.id===n){e=r,this._queue.splice(t,1);break}}}e&&e.abort()},css:function(e,t,n){return this._load("css",e,t,n)},js:function(e,t,n){return this._load("js",e,t,n)},load:function(e,t,n){return this._load(null,e,t,n)},_autoPurge:function(e){e&&this._purgeNodes.length>=e&&this._purge(this._purgeNodes)},_getEnv:function(){var t=e.config.doc,n=e.UA;return this._env={async:t&&t.createElement("script").async===!0||n.ie>=10,cssFail:n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0,cssLoad:(!n.gecko&&!n.webkit||n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0)&&!(n.chrome&&n.chrome<=18),preservesScriptOrder:!!(n.gecko||n.opera||n.ie&&n.ie>=10)}},_getTransaction:function(t,r){var i=[],o,u,a,f;n.isArray(t)||(t=[t]),r=e.merge(this.options,r),r.attributes=e.merge(this.options.attributes,r.attributes);for(o=0,u=t.length;o<u;++o){f=t[o],a={attributes:{}};if(typeof f=="string")a.url=f;else{if(!f.url)continue;e.mix(a,f,!1,null,0,!0),f=f.url}e.mix(a,r,!1,null,0,!0),a.type||(this.REGEX_CSS.test(f)?a.type="css":(!this.REGEX_JS.test(f),a.type="js")),e.mix(a,a.type==="js"?this.jsOptions:this.cssOptions,!1,null,0,!0),a.attributes.id||(a.attributes.id=e.guid()),a.win?a.doc=a.win.document:a.win=a.doc.defaultView||a.doc.parentWindow,a.charset&&(a.attributes.charset=a.charset),i.push(a)}return new s(i,r)},_load:function(e,t,n,r){var s;return typeof n=="function"&&(r=n,n={}),n||(n={}),n.type=e,n._onFinish=i._onTransactionFinish,this._env||this._getEnv(),s=this._getTransaction(t,n),this._queue.push({callback:r,transaction:s}),this._next(),s},_onTransactionFinish:function(){i._pending=null,i._next()},_next:function(){var e;if(this._pending)return;e=this._queue.shift(),e&&(this._pending=e,e.transaction.execute(e.callback))},_purge:function(t){var n=this._purgeNodes,r=t!==n,i,s;while(s=t.pop()){if(!s._yuiget_finished)continue;s.parentNode&&s.parentNode.removeChild(s),r&&(i=e.Array.indexOf(n,s),i>-1&&n.splice(i,1))}}},i.script=i.js,i.Transaction=s=function(t,n){var r=this;r.id=s._lastId+=1,r.data=n.data,r.errors=[],r.nodes=[],r.options=n,r.requests=t,r._callbacks=[],r._queue=[],r._reqsWaiting=0,r.tId=r.id,r.win=n.win||e.config.win},s._lastId=0,s.prototype={_state:"new",abort:function(e){this._pending=null,this._pendingCSS=null,this._pollTimer=clearTimeout(this._pollTimer),this._queue=[],this._reqsWaiting=0,this.errors.push({error:e||"Aborted"}),this._finish()},execute:function(e){var t=this,n=t.requests,r=t._state,i,s,o,u;if(r==="done"){e&&e(t.errors.length?t.errors:null,t);return}e&&t._callbacks.push(e);if(r==="executing")return;t._state="executing",t._queue=o=[],t.options.timeout&&(t._timeout=setTimeout(function(){t.abort("Timeout")},t.options.timeout)),t._reqsWaiting=n.length;for(i=0,s=n.length;i<s;++i)u=n[i],u.async||u.type==="css"?t._insert(u):o.push(u);t._next()},purge:function(){i._purge(this.nodes)},_createNode:function(e,t,n){var i=n.createElement(e),s,o;r||(o=n.createElement("div"),o.setAttribute("class","a"),r=o.className==="a"?{}:{"for":"htmlFor","class":"className"});for(s in t)t.hasOwnProperty(s)&&i.setAttribute(r[s]||s,t[s]);return i},_finish:function(){var e=this.errors.length?this.errors:null,t=this.options,n=t.context||this,r,i,s;if(this._state==="done")return;this._state="done";for(i=0,s=this._callbacks.length;i<s;++i)this._callbacks[i].call(n,e,this);r=this._getEventData(),e?(t.onTimeout&&e[e.length-1].error==="Timeout"&&t.onTimeout.call(n,r),t.onFailure&&t.onFailure.call(n,r)):t.onSuccess&&t.onSuccess.call(n,r),t.onEnd&&t.onEnd.call(n,r),t._onFinish&&t._onFinish()},_getEventData:function(t){return t?e.merge(this,{abort:this.abort,purge:this.purge,request:t,url:t.url,win:t.win}):this},_getInsertBefore:function(t){var n=t.doc,r=t.insertBefore,s,o,u;return r?typeof r=="string"?n.getElementById(r):r:(s=i._insertCache,u=e.stamp(n),(r=s[u])?r:(r=n.getElementsByTagName("base")[0])?s[u]=r:(r=n.head||n.getElementsByTagName("head")[0],r?(r.appendChild(n.createTextNode("")),s[u]=r.lastChild):s[u]=n.getElementsByTagName("script")[0]))},_insert:function(t){function c(){u._progress("Failed to load "+t.url,t)}function h(){f&&clearTimeout(f),u._progress(null,t)}var n=i._env,r=this._getInsertBefore(t),s=t.type==="js",o=t.node,u=this,a=e.UA,f,l;o||(s?l="script":!n.cssLoad&&a.gecko?l="style":l="link",o=t.node=this._createNode(l,t.attributes,t.doc)),s?(o.setAttribute("src",t.url),t.async?o.async=!0:(n.async&&(o.async=!1),n.preservesScriptOrder||(this._pending=t))):!n.cssLoad&&a.gecko?o.innerHTML=(t.attributes.charset?'@charset "'+t.attributes.charset+'";':"")+'@import "'+t.url+'";':o.setAttribute("href",t.url),s&&a.ie&&(a.ie<9||document.documentMode&&document.documentMode<9)?o.onreadystatechange=function(){/loaded|complete/.test(o.readyState)&&(o.onreadystatechange=null,h())}:!s&&!n.cssLoad?this._poll(t):(a.ie>=10?(o.onerror=function(){setTimeout(c,0)},o.onload=function(){setTimeout(h,0)}):(o.onerror=c,o.onload=h),!n.cssFail&&!s&&(f=setTimeout(c,t.timeout||3e3))),this.nodes.push(o),r.parentNode.insertBefore(o,r)},_next:function(){if(this._pending)return;this._queue.length?this._insert(this._queue.shift()):this._reqsWaiting||this._finish()},_poll:function(t){var n=this,r=n._pendingCSS,i=e.UA.webkit,s,o,u,a,f,l;if(t){r||(r=n._pendingCSS=[]),r.push(t);if(n._pollTimer)return}n._pollTimer=null;for(s=0;s<r.length;++s){f=r[s];if(i){l=f.doc.styleSheets,u=l.length,a=f.node.href;while(--u>=0)if(l[u].href===a){r.splice(s,1),s-=1,n._progress(null,f);break}}else try{o=!!f.node.sheet.cssRules,r.splice(s,1),s-=1,n._progress(null,f)}catch(c){}}r.length&&(n._pollTimer=setTimeout(function(){n._poll.call(n)},n.options.pollInterval))},_progress:function(e,t){var n=this.options;e&&(t.error=e,this.errors.push({error:e,request:t})),t.node._yuiget_finished=t.finished=!0,n.onProgress&&n.onProgress.call(n.context||this,this._getEventData(t)),t.autopurge&&(i._autoPurge(this.options.purgethreshold),i._purgeNodes.push(t.node)),this._pending===t&&(this._pending=null),this._reqsWaiting-=1,this._next()}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/graphics-canvas-default/graphics-canvas-default-min.js b/js/yui3/graphics-canvas-default/graphics-canvas-default-min.js
new file mode 100644
index 000000000..b104a2114
--- /dev/null
+++ b/js/yui3/graphics-canvas-default/graphics-canvas-default-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-canvas-default",function(e,t){e.Graphic=e.CanvasGraphic,e.Shape=e.CanvasShape,e.Circle=e.CanvasCircle,e.Rect=e.CanvasRect,e.Ellipse=e.CanvasEllipse,e.Path=e.CanvasPath,e.Drawing=e.CanvasDrawing},"3.7.3");
diff --git a/js/yui3/graphics-canvas/graphics-canvas-min.js b/js/yui3/graphics-canvas/graphics-canvas-min.js
new file mode 100644
index 000000000..3946b0e9e
--- /dev/null
+++ b/js/yui3/graphics-canvas/graphics-canvas-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-canvas",function(e,t){function T(){}function N(e){N.superclass.constructor.apply(this,arguments)}var n="canvas",r="shape",i=/[a-z][^a-z]*/ig,s=/[-]?[0-9]*[0-9|\.][0-9]*/g,o=e.config.doc,u=e.Lang,a=e.AttributeLite,f,l,c,h,p,d,v=e.DOM,m=e.Color,g=parseInt,y=parseFloat,b=u.isNumber,w=RegExp,E=m.toRGB,S=m.toHex,x=e.ClassNameManager.getClassName;T.prototype={_pathSymbolToMethod:{M:"moveTo",m:"relativeMoveTo",L:"lineTo",l:"relativeLineTo",C:"curveTo",c:"relativeCurveTo",Q:"quadraticCurveTo",q:"relativeQuadraticCurveTo",z:"closePath",Z:"closePath"},_currentX:0,_currentY:0,_toRGBA:function(e,t){return t=t!==undefined?t:1,m.re_RGB.test(e)||(e=S(e)),m.re_hex.exec(e)&&(e="rgba("+[g(w.$1,16),g(w.$2,16),g(w.$3,16)].join(",")+","+t+")"),e},_toRGB:function(e){return E(e)},setSize:function(e,t){this.get("autoSize")&&(e>this.node.getAttribute("width")&&(this.node.style.width=e+"px",this.node.setAttribute("width",e)),t>this.node.getAttribute("height")&&(this.node.style.height=t+"px",this.node.setAttribute("height",t)))},_updateCoords:function(e,t){this._xcoords.push(e),this._ycoords.push(t),this._currentX=e,this._currentY=t},_clearAndUpdateCoords:function(){var e=this._xcoords.pop()||0,t=this._ycoords.pop()||0;this._updateCoords(e,t)},_updateNodePosition:function(){var e=this.get("node"),t=this.get("x"),n=this.get("y");e.style.position="absolute",e.style.left=t+this._left+"px",e.style.top=n+this._top+"px"},_updateDrawingQueue:function(e){this._methods.push(e)},lineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!1])},relativeLineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!0])},_lineTo:function(e,t){var n=e[0],r,i,s,o,u=this._stroke&&this._strokeWeight?this._strokeWeight:0,a=t?parseFloat(this._currentX):0,f=t?parseFloat(this._currentY):0;this._lineToMethods||(this._lineToMethods=[]),i=e.length-1;if(typeof n=="string"||typeof n=="number")for(r=0;r<i;r+=2)s=parseFloat(e[r]),o=parseFloat(e[r+1]),s+=a,o+=f,this._updateDrawingQueue(["lineTo",s,o]),this._trackSize(s-u,o-u),this._trackSize(s+u,o+u),this._updateCoords(s,o);else for(r=0;r<i;r+=1)s=parseFloat(e[r][0]),o=parseFloat(e[r][1]),this._updateDrawingQueue(["lineTo",s,o]),this._lineToMethods[this._lineToMethods.length]=this._methods[this._methods.length-1],this._trackSize(s-u,o-u),this._trackSize(s+u,o+u),this._updateCoords(s,o);return this._drawingComplete=!1,this},moveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!1])},relativeMoveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!0])},_moveTo:function(e,t){var n=this._stroke&&this._strokeWeight?this._strokeWeight:0,r=t?parseFloat(this._currentX):0,i=t?parseFloat(this._currentY):0,s=parseFloat(e[0])+r,o=parseFloat(e[1])+i;return this._updateDrawingQueue(["moveTo",s,o]),this._trackSize(s-n,o-n),this._trackSize(s+n,o+n),this._updateCoords(s,o),this._drawingComplete=!1,this},curveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!1])},relativeCurveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!0])},_curveTo:function(e,t){var n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g=t?parseFloat(this._currentX):0,y=t?parseFloat(this._currentY):0;m=e.length-5;for(v=0;v<m;v+=6)i=parseFloat(e[v])+g,s=parseFloat(e[v+1])+y,o=parseFloat(e[v+2])+g,u=parseFloat(e[v+3])+y,a=parseFloat(e[v+4])+g,f=parseFloat(e[v+5])+y,this._updateDrawingQueue(["bezierCurveTo",i,s,o,u,a,f]),this._drawingComplete=!1,c=Math.max(a,Math.max(i,o)),p=Math.max(f,Math.max(s,u)),h=Math.min(a,Math.min(i,o)),d=Math.min(f,Math.min(s,u)),n=Math.abs(c-h),r=Math.abs(p-d),l=[[this._currentX,this._currentY],[i,s],[o,u],[a,f]],this._setCurveBoundingBox(l,n,r),this._currentX=a,this._currentY=f},quadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!1])},relativeQuadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!0])},_quadraticCurveTo:function(e,t){var n,r,i,s,o,u,a,f,l,c,h,p,d=e.length-3,v=this._stroke&&this._strokeWeight?this._strokeWeight:0,m=t?parseFloat(this._currentX):0,g=t?parseFloat(this._currentY):0;for(p=0;p<d;p+=4)n=parseFloat(e[p])+m,r=parseFloat(e[p+1])+g,i=parseFloat(e[p+2])+m,s=parseFloat(e[p+3])+g,this._drawingComplete=!1,f=Math.max(i,n),c=Math.max(s,r),l=Math.min(i,n),h=Math.min(s,r),o=Math.abs(f-l),u=Math.abs(c-h),a=[[this._currentX,this._currentY],[n,r],[i,s]],this._setCurveBoundingBox(a,o,u),this._updateDrawingQueue(["quadraticCurveTo",n,r,i,s]),this._updateCoords(i,s);return this},drawCircle:function(e,t,n){var r=0,i=2*Math.PI,s=this._stroke&&this._strokeWeight?this._strokeWeight:0,o=n*2;return o+=s,this._drawingComplete=!1,this._trackSize(e+o,t+o),this._trackSize(e-s,t-s),this._updateCoords(e,t),this._updateDrawingQueue(["arc",e+n,t+n,n,r,i,!1]),this},drawDiamond:function(e,t,n,r){var i=n*.5,s=r*.5;return this.moveTo(e+i,t),this.lineTo(e+n,t+s),this.lineTo(e+i,t+r),this.lineTo(e,t+s),this.lineTo(e+i,t),this},drawEllipse:function(e,t,n,r){var i=8,s=-0.25*Math.PI,o=0,u,a=n/2,f=r/2,l,c=e+a,h=t+f,p,d,v,m,g,y,b=this._stroke&&this._strokeWeight?this._strokeWeight:0;p=c+Math.cos(0)*a,d=h+Math.sin(0)*f,this.moveTo(p,d);for(l=0;l<i;l++)o+=s,u=o-s/2,v=c+Math.cos(o)*a,m=h+Math.sin(o)*f,g=c+Math.cos(u)*(a/Math.cos(s/2)),y=h+Math.sin(u)*(f/Math.cos(s/2)),this._updateDrawingQueue(["quadraticCurveTo",g,y,v,m]);return this._trackSize(e+n+b,t+r+b),this._trackSize(e-b,t-b),this._updateCoords(e,t),this},drawRect:function(e,t,n,r){var i=this._stroke&&this._strokeWeight?this._strokeWeight:0;return this._drawingComplete=!1,this.moveTo(e,t),this.lineTo(e+n,t),this.lineTo(e+n,t+r),this.lineTo(e,t+r),this.lineTo(e,t),this},drawRoundRect:function(e,t,n,r,i,s){var o=this._stroke&&this._strokeWeight?this._strokeWeight:0;return this._drawingComplete=!1,this.moveTo(e,t+s),this.lineTo(e,t+r-s),this.quadraticCurveTo(e,t+r,e+i,t+r),this.lineTo(e+n-i,t+r),this.quadraticCurveTo(e+n,t+r,e+n,t+r-s),this.lineTo(e+n,t+s),this.quadraticCurveTo(e+n,t,e+n-i,t),this.lineTo(e+i,t),this.quadraticCurveTo(e,t,e,t+s),this},drawWedge:function(e,t,n,r,i,s){var o=this._stroke&&this._strokeWeight?this._strokeWeight:0,u,a,f,l,c,h,p,d,v,m,g,y=0;s=s||i,this._drawingComplete=!1,this._updateDrawingQueue(["moveTo",e,t]),s=s||i,Math.abs(r)>360&&(r=360),u=Math.ceil(Math.abs(r)/45),a=r/u,f=-(a/180)*Math.PI,l=n/180*Math.PI;if(u>0){h=e+Math.cos(n/180*Math.PI)*i,p=t+Math.sin(n/180*Math.PI)*s,this.lineTo(h,p);for(y=0;y<u;++y)l+=f,c=l-f/2,d=e+Math.cos(l)*i,v=t+Math.sin(l)*s,m=e+Math.cos(c)*(i/Math.cos(f/2)),g=t+Math.sin(c)*(s/Math.cos(f/2)),this._updateDrawingQueue(["quadraticCurveTo",m,g,d,v]);this._updateDrawingQueue(["lineTo",e,t])}return this._trackSize(-o,-o),this._trackSize(i*2+o,i*2+o),this},end:function(){return this._closePath(),this},closePath:function(){this._updateDrawingQueue(["closePath"]),this._updateDrawingQueue(["beginPath"])},_getLinearGradient:function(){var t=e.Lang.isNumber,n=this.get("fill"),r=n.stops,i,s,o,u,a=r.length,f,l=0,c=0,h=this.get("width"),p=this.get("height"),d=n.rotation||0,v,m,g,y,b=l+h/2,w=c+p/2,S,x=Math.PI/180,T=parseFloat(parseFloat(Math.tan(d*x)).toFixed(8));Math.abs(T)*h/2>=p/2?(d<180?(g=c,y=c+p):(g=c+p,y=c),v=b-(w-g)/T,m=b-(w-y)/T):(d>90&&d<270?(v=l+h,m=l):(v=l,m=l+h),g=(T*(b-v)-w)*-1,y=(T*(b-m)-w)*-1),f=this._context.createLinearGradient(v,g,m,y);for(u=0;u<a;++u)o=r[u],i=o.opacity,s=o.color,S=o.offset,t(i)?(i=Math.max(0,Math.min(1,i)),s=this._toRGBA(s,i)):s=E(s),S=o.offset||u/(a-1),f.addColorStop(S,s);return f},_getRadialGradient:function(){var t=e.Lang.isNumber,n=this.get("fill"),r=n.r,i=n.fx,s=n.fy,o=n.stops,u,a,f,l,c=o.length,h,p=0,d=0,v=this.get("width"),m=this.get("height"),g,y,b,w,S,x,T,N,C,k,L,A,O;x=p+v/2,T=d+m/2,g=v*i,b=m*s,y=p+v/2,w=d+m/2,S=v*r,k=Math.sqrt(Math.pow(Math.abs(x-g),2)+Math.pow(Math.abs(T-b),2)),k>=S&&(A=k/S,A===1&&(A=1.01),N=(g-x)/A,C=(b-T)/A,N=N>0?Math.floor(N):Math.ceil(N),C=C>0?Math.floor(C):Math.ceil(C),g=x+N,b=T+C),r>=.5?(h=this._context.createRadialGradient(g,b,r,y,w,r*v),O=1):(h=this._context.createRadialGradient(g,b,r,y,w,v/2),O=r*2);for(l=0;l<c;++l)f=o[l],u=f.opacity,a=f.color,L=f.offset,t(u)?(u=Math.max(0,Math.min(1,u)),a=this._toRGBA(a,u)):a=E(a),L=f.offset||l/(c-1),L*=O,L<=1&&h.addColorStop(L,a);return h},_initProps:function(){this._methods=[],this._lineToMethods=[],this._xcoords=[0],this._ycoords=[0],this._width=0,this._height=0,this._left=0,this._top=0,this._right=0,this._bottom=0,this._currentX=0,this._currentY=0},_drawingComplete:!1,_createGraphic:function(t){var n=e.config.doc.createElement("canvas");return n},getBezierData:function(e,t){var n=e.length,r=[],i,s;for(i=0;i<n;++i)r[i]=[e[i][0],e[i][1]];for(s=1;s<n;++s)for(i=0;i<n-s;++i)r[i][0]=(1-t)*r[i][0]+t*r[parseInt(i+1,10)][0],r[i][1]=(1-t)*r[i][1]+t*r[parseInt(i+1,10)][1];return[r[0][0],r[0][1]]},_setCurveBoundingBox:function(e,t,n){var r=0,i=this._currentX,s=i,o=this._currentY,u=o,a=Math.round(Math.sqrt(t*t+n*n)),f=1/a,l=this._stroke&&this._strokeWeight?this._strokeWeight:0,c;for(r=0;r<a;++r)c=this.getBezierData(e,f*r),i=isNaN(i)?c[0]:Math.min(c[0],i),s=isNaN(s)?c[0]:Math.max(c[0],s),o=isNaN(o)?c[1]:Math.min(c[1],o),u=isNaN(u)?c[1]:Math.max(c[1],u);i=Math.round(i*10)/10,s=Math.round(s*10)/10,o=Math.round(o*10)/10,u=Math.round(u*10)/10,this._trackSize(s+l,u+l),this._trackSize(i-l,o-l)},_trackSize:function(e,t){e>this._right&&(this._right=e),e<this._left&&(this._left=e),t<this._top&&(this._top=t),t>this._bottom&&(this._bottom=t),this._width=this._right-this._left,this._height=this._bottom-this._top}},e.CanvasDrawing=T,f=function(t){this._transforms=[],this.matrix=new e.Matrix,f.superclass.constructor.apply(this,arguments)},f.NAME="shape",e.extend(f,e.GraphicBase,e.mix({init:function(){this.initializer.apply(this,arguments)},initializer:function(e){var t=this,n=e.graphic,r=this.get("data");t._initProps(),t.createNode(),t._xcoords=[0],t._ycoords=[0],n&&this._setGraphic(n),r&&t._parsePathData(r),t._updateHandler()},_setGraphic:function(t){var n;t instanceof e.CanvasGraphic?this._graphic=t:(t=e.one(t),n=new e.CanvasGraphic({render:t}),n._appendShape(this),this._graphic=n)},addClass:function(t){var n=e.one(this.get("node"));n.addClass(t)},removeClass:function(t){var n=e.one(this.get("node"));n.removeClass(t)},getXY:function(){var e=this.get("graphic"),t=e.getXY(),n=this.get("x"),r=this.get("y");return[t[0]+n,t[1]+r]},setXY:function(e){var t=this.get("graphic"),n=t.getXY(),r=e[0]-n[0],i=e[1]-n[1];this._set("x",r),this._set("y",i),this._updateNodePosition(r,i)},contains:function(t){return t===e.one(this.node)},test:function(t){return e.one(this.get("node")).test(t)},compareTo:function(e){var t=this.node;return t===e},_getDefaultFill:function(){return{type:"solid",opacity:1,cx:.5,cy:.5,fx:.5,fy:.5,r:.5}},_getDefaultStroke:function(){return{weight:1,dashstyle:"none",color:"#000",opacity:1}},_left:0,_right:0,_top:0,_bottom:0,createNode:function(){var t=this,i=e.config.doc.createElement("canvas"),s=t.get("id"),o=t._camelCaseConcat,u=t.name;t._context=i.getContext("2d"),i.setAttribute("overflow","visible"),i.style.overflow="visible",t.get("visible")||(i.style.visibility="hidden"),i.setAttribute("id",s),s="#"+s,t.node=i,t.addClass(x(r)+" "+x(o(n,r))+" "+x(u)+" "+x(o(n,u)))},on:function(t,n){return e.Node.DOM_EVENTS[t]?e.one("#"+this.get("id")).on(t,n):e.on.apply(this,arguments)},_setStrokeProps:function(t){var n,r,i,s,o,u;t?(n=t.color,r=y(t.weight),i=y(t.opacity),s=t.linejoin||"round",o=t.linecap||"butt",u=t.dashstyle,this._miterlimit=null,this._dashstyle=u&&e.Lang.isArray(u)&&u.length>1?u:null,this._strokeWeight=r,b(r)&&r>0?this._stroke=1:this._stroke=0,b(i)?this._strokeStyle=this._toRGBA(n,i):this._strokeStyle=n,this._linecap=o,s=="round"||s=="bevel"?this._linejoin=s:(s=parseInt(s,10),b(s)&&(this._miterlimit=Math.max(s,1),this._linejoin="miter"))):this._stroke=0},set:function(){var e=this,t=arguments[0];a.prototype.set.apply(e,arguments),e.initialized&&e._updateHandler()},_setFillProps:function(e){var t=b,n,r,i;e?(n=e.color,i=e.type,i=="linear"||i=="radial"?this._fillType=i:n?(r=e.opacity,t(r)?(r=Math.max(0,Math.min(1,r)),n=this._toRGBA(n,r)):n=E(n),this._fillColor=n,this._fillType="solid"):this._fillColor=null):(this._fillType=null,this._fillColor=null)},translate:function(e,t){this._translateX+=e,this._translateY+=t,this._addTransform("translate",arguments)},translateX:function(e){this._translateX+=e,this._addTransform("translateX",arguments)},translateY:function(e){this._translateY+=e,this._addTransform("translateY",arguments)},skew:function(e,t){this._addTransform("skew",arguments)},skewX:function(e){this._addTransform("skewX",arguments)},skewY:function(e){this._addTransform("skewY",arguments)},rotate:function(e){this._rotation=e,this._addTransform("rotate",arguments)},scale:function(e,t){this._addTransform("scale",arguments)},_rotation:0,_transform:"",_addTransform:function(t,n){n=e.Array(n),this._transform=u.trim(this._transform+" "+t+"("+n.join(", ")+")"),n.unshift(t),this._transforms.push(n),this.initialized&&this._updateTransform()},_updateTransform:function(){var e=this.node,t,n,r=this.get("transformOrigin"),i=this.matrix,s,o=this._transforms.length;if(this._transforms&&this._transforms.length>0){for(s=0;s<o;++s)t=this._transforms[s].shift(),t&&i[t].apply(i,this._transforms[s]);n=i.toCSSText()}this._graphic.addToRedrawQueue(this),r=100*r[0]+"% "+100*r[1]+"%",v.setStyle(e,"transformOrigin",r),n&&v.setStyle(e,"transform",n),this._transforms=[]},_updateHandler:function(){this._draw(),this._updateTransform()},_draw:function(){var e=this.node;this.clear(),this._closePath(),e.style.left=this.get("x")+"px",e.style.top=this.get("y")+"px"},_closePath:function(){if(!this._methods)return;var e=this.get("node"),t=this._right-this._left,n=this._bottom-this._top,r=this._context,i=[],s=this._methods.concat(),o,u,a,f,l,c=0;this._context.clearRect(0,0,e.width,e.height);if(this._methods){c=s.length;if(!c||c<1)return;for(o=0;o<c;++o){i[o]=s[o].concat(),f=i[o],l=f[0]=="quadraticCurveTo"||f[0]=="bezierCurveTo"?f.length:3;for(u=1;u<l;++u)u%2===0?f[u]=f[u]-this._top:f[u]=f[u]-this._left}e.setAttribute("width",Math.min(t,2e3)),e.setAttribute("height",Math.min(2e3,n)),r.beginPath();for(o=0;o<c;++o)f=i[o].concat(),f&&f.length>0&&(a=f.shift(),a&&(a=="closePath"?(r.closePath(),this._strokeAndFill(r)):a&&a=="lineTo"&&this._dashstyle?(f.unshift(this._xcoords[o]-this._left,this._ycoords[o]-this._top),this._drawDashedLine.apply(this,f)):r[a].apply(r,f)));this._strokeAndFill(r),this._drawingComplete=!0,this._clearAndUpdateCoords(),this._updateNodePosition(),this._methods=s}},_strokeAndFill:function(e){this._fillType&&(this._fillType=="linear"?e.fillStyle=this._getLinearGradient():this._fillType=="radial"?e.fillStyle=this._getRadialGradient():e.fillStyle=this._fillColor,e.closePath(),e.fill()),this._stroke&&(this._strokeWeight&&(e.lineWidth=this._strokeWeight),e.lineCap=this._linecap,e.lineJoin=this._linejoin,this._miterlimit&&(e.miterLimit=this._miterlimit),e.strokeStyle=this._strokeStyle,e.stroke())},_drawDashedLine:function(e,t,n,r){var i=this._context,s=this._dashstyle[0],o=this._dashstyle[1],u=s+o,a=n-e,f=r-t,l=Math.sqrt(Math.pow(a,2)+Math.pow(f,2)),c=Math.floor(Math.abs(l/u)),h=Math.atan2(f,a),p=e,d=t,v;a=Math.cos(h)*u,f=Math.sin(h)*u;for(v=0;v<c;++v)i.moveTo(p,d),i.lineTo(p+Math.cos(h)*s,d+Math.sin(h)*s),p+=a,d+=f;i.moveTo(p,d),l=Math.sqrt((n-p)*(n-p)+(r-d)*(r-d)),l>s?i.lineTo(p+Math.cos(h)*s,d+Math.sin(h)*s):l>0&&i.lineTo(p+Math.cos(h)*l,d+Math.sin(h)*l),i.moveTo(n,r)},clear:function(){return this._initProps(),this.node&&this._context.clearRect(0,0,this.node.width,this.node.height),this},getBounds:function(){var e=this._type,t=this.get("width"),n=this.get("height"),r=this.get("x"),i=this.get("y");return e=="path"&&(r+=this._left,i+=this._top,t=this._right-this._left,n=this._bottom-this._top),this._getContentRect(t,n,r,i)},_getContentRect:function(t,n,r,i){var s=this.get("transformOrigin"),o=s[0]*t,u=s[1]*n,a=this.matrix.getTransformArray(this.get("transform")),f=new e.Matrix,l,c=a.length,h,p,d;this._type=="path"&&(o+=r,u+=i),o=isNaN(o)?0:o,u=isNaN(u)?0:u,f.translate(o,u);for(l=0;l<c;l+=1)h=a[l],p=h.shift(),p&&f[p].apply(f,h);return f.translate(-o,-u),d=f.getContentRect(t,n,r,i),d},toFront:function(){var e=this.get("graphic");e&&e._toFront(this)},toBack:function(){var e=this.get("graphic");e&&e._toBack(this)},_parsePathData:function(t){var n,r,o,u=e.Lang.trim(t.match(i)),a,f,l,c=this._pathSymbolToMethod;if(u){this.clear(),f=u.length||0;for(a=0;a<f;a+=1)l=u[a],r=l.substr(0,1),o=l.substr(1).match(s),n=c[r],n&&(o?this[n].apply(this,o):this[n].apply(this));this.end()}},destroy:function(){var e=this.get("graphic");e?e.removeShape(this):this._destroy()},_destroy:function(){this.node&&(e.one(this.node).remove(!0),this._context=null,this.node=null)}},e.CanvasDrawing.prototype)),f.ATTRS={transformOrigin:{valueFn:function(){return[.5,.5]}},transform:{setter:function(e){return this.matrix.init(),this._transforms=this.matrix.getTransformArray(e),this._transform=e,e},getter:function(){return this._transform}},node:{readOnly:!0,getter:function(){return this.node}},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this.node;return t&&t.setAttribute("id",e),e}},width:{value:0},height:{value:0},x:{value:0},y:{value:0},visible:{value:!0,setter:function(e){var t=this.get("node"),n=e?"visible":"hidden";return t&&(t.style.visibility=n),e}},fill:{valueFn:"_getDefaultFill",setter:function(t){var n,r=this.get("fill")||this._getDefaultFill();return n=t?e.merge(r,t):null,n&&n.color&&(n.color===undefined||n.color=="none")&&(n.color=null),this._setFillProps(n),n}},stroke:{valueFn:"_getDefaultStroke",setter:function(t){var n=this.get("stroke")||this._getDefaultStroke(),r;return t&&t.hasOwnProperty("weight")&&(r=parseInt(t.weight,10),isNaN(r)||(t.weight=r)),t=t?e.merge(n,t):null,this._setStrokeProps(t),t}},autoSize:{value:!1},pointerEvents:{value:"visiblePainted"},data:{setter:function(e){return this.get("node")&&this._parsePathData(e),e}},graphic:{readOnly:!0,getter:function(){return this._graphic}}},e.CanvasShape=f,l=function(e){l.superclass.constructor.apply(this,arguments)},l.NAME="path",e.extend(l,e.CanvasShape,{_type:"path",_draw:function(){this._closePath(),this._updateTransform()},createNode:function(){var t=this,i=e.config.doc.createElement("canvas"),s=t.name,o=t._camelCaseConcat,u=t.get("id");t._context=i.getContext("2d"),i.setAttribute("overflow","visible"),i.setAttribute("pointer-events","none"),i.style.pointerEvents="none",i.style.overflow="visible",i.setAttribute("id",u),u="#"+u,t.node=i,t.addClass(x(r)+" "+x(o(n,r))+" "+x(s)+" "+x(o(n,s)))},end:function(){this._draw()}}),l.ATTRS=e.merge(e.CanvasShape.ATTRS,{width:{getter:function(){var e=this._stroke&&this._strokeWeight?this._strokeWeight*2:0;return this._width-e},setter:function(e){return this._width=e,e}},height:{getter:function(){var e=this._stroke&&this._strokeWeight?this._strokeWeight*2:0;return this._height-e},setter:function(e){return this._height=e,e}},path:{readOnly:!0,getter:function(){return this._path}}}),e.CanvasPath=l,c=function(){c.superclass.constructor.apply(this,arguments)},c.NAME="rect",e.extend(c,e.CanvasShape,{_type:"rect",_draw:function(){var e=this.get("width"),t=this.get("height");this.clear(),this.drawRect(0,0,e,t),this._closePath()}}),c.ATTRS=e.CanvasShape.ATTRS,e.CanvasRect=c,h=function(e){h.superclass.constructor.apply(this,arguments)},h.NAME="ellipse",e.extend(h,f,{_type:"ellipse",_draw:function(){var e=this.get("width"),t=this.get("height");this.clear(),this.drawEllipse(0,0,e,t),this._closePath()}}),h.ATTRS=e.merge(f.ATTRS,{xRadius:{setter:function(e){this.set("width",e*2)},getter:function(){var e=this.get("width");return e&&(e*=.5),e}},yRadius:{setter:function(e){this.set("height",e*2)},getter:function(){var e=this.get("height");return e&&(e*=.5),e}}}),e.CanvasEllipse=h,p=function(e){p.superclass.constructor.apply(this,arguments)},p.NAME="circle",e.extend(p,e.CanvasShape,{_type:"circle",_draw:function(){var e=this.get("radius");e&&(this.clear(),this.drawCircle(0,0,e),this._closePath())}}),p.ATTRS=e.merge(e.CanvasShape.ATTRS,{width:{setter:function(e){return this.set("radius",e/2),e},getter:function(){return this.get("radius")*2}},height:{setter:function(e){return this.set("radius",e/2),e},getter:function(){return this.get("radius")*2}},radius:{lazyAdd:!1}}),e.CanvasCircle=p,d=function(){d.superclass.constructor.apply(this,arguments)},d.NAME="canvasPieSlice",e.extend(d,e.CanvasShape,{_type:"path",_draw:function(e){var t=this.get("cx"),n=this.get("cy"),r=this.get("startAngle"),i=this.get("arc"),s=this.get("radius");this.clear(),this._left=t,this._right=s,this._top=n,this._bottom=s,this.drawWedge(t,n,r,i,s),this.end()}}),d.ATTRS=e.mix({cx:{value:0},cy:{value:0},startAngle:{value:0},arc:{value:0},radius:{value:0}},e.CanvasShape.ATTRS),e.CanvasPieSlice=d,N.NAME="canvasGraphic",N.ATTRS={render:{},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this._node;return t&&t.setAttribute("id",e),e}},shapes:{readOnly:!0,getter:function(){return this._shapes}},contentBounds:{readOnly:!0,getter:function(){return this._contentBounds}},node:{readOnly:!0,getter:function(){return this._node}},width:{setter:function(e){return this._node&&(this._node.style.width=e+"px"),e}},height:{setter:function(e){return this._node&&(this._node.style.height=e+"px"),e}},autoSize:{value:!1},preserveAspectRatio:{value:"xMidYMid"},resizeDown:{value:!1},x:{getter:function(){return this._x},setter:function(e){return this._x=e,this._node&&(this._node.style.left=e+"px"),e}},y:{getter:function(){return this._y},setter:function(e){return this._y=e,this._node&&(this._node.style.top=e+"px"),e}},autoDraw:{value:!0},visible:{value:!0,setter:function(e){return this._toggleVisible(e),e}}},e.extend(N,e.GraphicBase,{set:function(t,n){var r=this,i={autoDraw:!0,autoSize:!0,preserveAspectRatio:!0,resizeDown:!0},s,o=!1;a.prototype.set.apply(r,arguments);if(r._state.autoDraw===!0&&e.Object.size(this._shapes)>0)if(u.isString&&i[t])o=!0;else if(u.isObject(t))for(s in i)if(i.hasOwnProperty(s)&&t[s]){o=!0;break}o&&r._redraw()},_x:0,_y:0,getXY:function(){var t=e.one(this._node),n;return t&&(n=t.getXY()),n},initializer:function(e){var t=this.get("render"),n=this.get("visible")?"visible":"hidden",r=this.get("width")||0,i=this.get("height")||0;this._shapes={},this._redrawQueue={},this._contentBounds={left:0,top:0,right:0,bottom:0},this._node=o.createElement("div"),this._node.style.position="absolute",this._node.style.visibility=n,this.set("width",r),this.set("height",i),t&&this.render(t)},render:function(t){var n=e.one(t),r=this._node,i=this.get("width")||parseInt(n.getComputedStyle("width"),10),s=this.get("height")||parseInt(n.getComputedStyle("height"),10);return n=n||o.body,n.appendChild(r),r.style.display="block",r.style.position="absolute",r.style.left="0px",r.style.top="0px",this.set("width",i),this.set("height",s),this.parentNode=n,this},destroy:function(){this.removeAllShapes(),this._node&&(this._removeChildren(this._node),e.one(this._node).destroy())},addShape:function(e){e.graphic=this,this.get("visible")||(e.visible=!1);var t=this._getShapeClass(e.type),n=new t(e);return this._appendShape(n),n},_appendShape:function(e){var t=e.node,n=this._frag||this._node;this.get("autoDraw")?n.appendChild(t):this._getDocFrag().appendChild(t)},removeShape:function(e){return e instanceof f||u.isString(e)&&(e=this._shapes[e]),e&&e instanceof f&&(e._destroy(),delete this._shapes[e.get("id")]),this.get("autoDraw")&&this._redraw(),e},removeAllShapes:function(){var e=this._shapes,t;for(t in e)e.hasOwnProperty(t)&&e[t].destroy();this._shapes={}},clear:function(){this.removeAllShapes()},_removeChildren:function(e){if(e&&e.hasChildNodes()){var t;while(e.firstChild)t=e.firstChild,this._removeChildren(t),e.removeChild(t)}},_toggleVisible:function(e){var t,n=this._shapes,r=e?"visible":"hidden";if(n)for(t in n)n.hasOwnProperty(t)&&n[t].set("visible",e);this._node&&(this._node.style.visibility=r)},_getShapeClass:function(e){var t=this._shapeClass[e];return t?t:e},_shapeClass:{circle:e.CanvasCircle,rect:e.CanvasRect,path:e.CanvasPath,ellipse:e.CanvasEllipse,pieslice:e.CanvasPieSlice},getShapeById:function(e){var t=this._shapes[e];return t},batch:function(e){var t=this.get("autoDraw");this.set("autoDraw",!1),e(),this.set("autoDraw",t)},_getDocFrag:function(){return this._frag||(this._frag=o.createDocumentFragment()),this._frag},_redraw:function(){var t=this.get("autoSize"),n=this.get("preserveAspectRatio"),r=this.get("resizeDown")?this._getUpdatedContentBounds():this._contentBounds,i,s,o,u,a,f,l=0,c=0,h,p=this.get("node");t&&(t=="sizeContentToGraphic"?(i=r.right-r.left,s=r.bottom-r.top,o=parseFloat(v.getComputedStyle(p,"width")),u=parseFloat(v.getComputedStyle(p,"height")),h=new e.Matrix,n=="none"?(a=o/i,f=u/s):i/s!==o/u&&(i*u/s>o?(a=f=o/i,c=this._calculateTranslate(n.slice(5).toLowerCase(),s*o/i,u)):(a=f=u/s,l=this._calculateTranslate(n.slice(1,4).toLowerCase(),i*u/s,o))),v.setStyle(p,"transformOrigin","0% 0%"),l-=r.left*a,c-=r.top*f,h.translate(l,c),h.scale(a,f),v.setStyle(p,"transform",h.toCSSText())):(this.set("width",r.right),this.set("height",r.bottom))),this._frag&&(this._node.appendChild(this._frag),this._frag=null)},_calculateTranslate:function(e,t,n){var r=n-t,i;switch(e){case"mid":i=r*.5;break;case"max":i=r;break;default:i=0}return i},addToRedrawQueue:function(e){var t,n;this._shapes[e.get("id")]=e,this.get("resizeDown")||(t=e.getBounds(),n=this._contentBounds,n.left=n.left<t.left?n.left:t.left,n.top=n.top<t.top?n.top:t.top,n.right=n.right>t.right?n.right:t.right,n.bottom=n.bottom>t.bottom?n.bottom:t.bottom,this._contentBounds=n),this.get("autoDraw")&&this._redraw()},_getUpdatedContentBounds:function(){var e,t,n,r=this._shapes,i={};for(t in r)r.hasOwnProperty(t)&&(n=r[t],e=n.getBounds(),i.left=u.isNumber(i.left)?Math.min(i.left,e.left):e.left,i.top=u.isNumber(i.top)?Math.min(i.top,e.top):e.top,i.right=u.isNumber(i.right)?Math.max(i.right,e.right):e.right,i.bottom=u.isNumber(i.bottom)?Math.max(i.bottom,e.bottom):e.bottom);return i.left=u.isNumber(i.left)?i.left:0,i.top=u.isNumber(i.top)?i.top:0,i.right=u.isNumber(i.right)?i.right:0,i.bottom=u.isNumber(i.bottom)?i.bottom:0,this._contentBounds=i,i},_toFront:function(t){var n=this.get("node");t instanceof e.CanvasShape&&(t=t.get("node")),n&&t&&n.appendChild(t)},_toBack:function(t){var n=this.get("node"),r;t instanceof e.CanvasShape&&(t=t.get("node")),n&&t&&(r=n.firstChild,r?n.insertBefore(t,r):n.appendChild(t))}}),e.CanvasGraphic=N},"3.7.3",{requires:["graphics"]});
diff --git a/js/yui3/graphics-svg-default/graphics-svg-default-min.js b/js/yui3/graphics-svg-default/graphics-svg-default-min.js
new file mode 100644
index 000000000..693315d92
--- /dev/null
+++ b/js/yui3/graphics-svg-default/graphics-svg-default-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-svg-default",function(e,t){e.Graphic=e.SVGGraphic,e.Shape=e.SVGShape,e.Circle=e.SVGCircle,e.Rect=e.SVGRect,e.Ellipse=e.SVGEllipse,e.Path=e.SVGPath,e.Drawing=e.SVGDrawing},"3.7.3");
diff --git a/js/yui3/graphics-svg/graphics-svg-min.js b/js/yui3/graphics-svg/graphics-svg-min.js
new file mode 100644
index 000000000..748bcf209
--- /dev/null
+++ b/js/yui3/graphics-svg/graphics-svg-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-svg",function(e,t){function g(){}var n="svg",r="shape",i=/[a-z][^a-z]*/ig,s=/[-]?[0-9]*[0-9|\.][0-9]*/g,o=e.Lang,u=e.AttributeLite,a,f,l,c,h,p,d,v=e.config.doc,m=e.ClassNameManager.getClassName;g.prototype={_pathSymbolToMethod:{M:"moveTo",m:"relativeMoveTo",L:"lineTo",l:"relativeLineTo",C:"curveTo",c:"relativeCurveTo",Q:"quadraticCurveTo",q:"relativeQuadraticCurveTo",z:"closePath",Z:"closePath"},_currentX:0,_currentY:0,_type:"path",curveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!1])},relativeCurveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!0])},_curveTo:function(e,t){var n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b=t?"c":"C",w=t?parseFloat(this._currentX):0,E=t?parseFloat(this._currentY):0;this._pathArray=this._pathArray||[],this._pathType!==b?(this._pathType=b,y=[b],this._pathArray.push(y)):(y=this._pathArray[Math.max(0,this._pathArray.length-1)],y||(y=[],this._pathArray.push(y))),g=this._pathArray.length-1,this._pathArray[g]=this._pathArray[g].concat(e),m=e.length-5;for(v=0;v<m;v+=6)s=parseFloat(e[v])+w,o=parseFloat(e[v+1])+E,u=parseFloat(e[v+2])+w,a=parseFloat(e[v+3])+E,f=parseFloat(e[v+4])+w,l=parseFloat(e[v+5])+E,c=Math.max(f,Math.max(s,u)),p=Math.max(l,Math.max(o,a)),h=Math.min(f,Math.min(s,u)),d=Math.min(l,Math.min(o,a)),n=Math.abs(c-h),r=Math.abs(p-d),i=[[this._currentX,this._currentY],[s,o],[u,a],[f,l]],this._setCurveBoundingBox(i,n,r),this._currentX=f,this._currentY=l},quadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!1])},relativeQuadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!0])},_quadraticCurveTo:function(e,t){var n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g=t?"q":"Q",y=t?parseFloat(this._currentX):0,b=t?parseFloat(this._currentY):0;this._pathType!==g?(this._pathType=g,u=[g],this._pathArray.push(u)):(u=this._pathArray[Math.max(0,this._pathArray.length-1)],u||(u=[],this._pathArray.push(u))),o=this._pathArray.length-1,this._pathArray[o]=this._pathArray[o].concat(e),m=e.length-3;for(v=0;v<m;v+=4)n=parseFloat(e[v])+y,r=parseFloat(e[v+1])+b,i=parseFloat(e[v+2])+y,s=parseFloat(e[v+3])+b,c=Math.max(i,n),p=Math.max(s,r),h=Math.min(i,n),d=Math.min(s,r),a=Math.abs(c-h),f=Math.abs(p-d),l=[[this._currentX,this._currentY],[n,r],[i,s]],this._setCurveBoundingBox(l,a,f),this._currentX=i,this._currentY=s},drawRect:function(e,t,n,r){this.moveTo(e,t),this.lineTo(e+n,t),this.lineTo(e+n,t+r),this.lineTo(e,t+r),this.lineTo(e,t)},drawRoundRect:function(e,t,n,r,i,s){this.moveTo(e,t+s),this.lineTo(e,t+r-s),this.quadraticCurveTo(e,t+r,e+i,t+r),this.lineTo(e+n-i,t+r),this.quadraticCurveTo(e+n,t+r,e+n,t+r-s),this.lineTo(e+n,t+s),this.quadraticCurveTo(e+n,t,e+n-i,t),this.lineTo(e+i,t),this.quadraticCurveTo(e,t,e,t+s)},drawCircle:function(e,t,n){var r=n*2;return this._drawingComplete=!1,this._trackSize(e,t),this._trackSize(e+r,t+r),this._pathArray=this._pathArray||[],this._pathArray.push(["M",e+n,t]),this._pathArray.push(["A",n,n,0,1,0,e+n,t+r]),this._pathArray.push(["A",n,n,0,1,0,e+n,t]),this._currentX=e,this._currentY=t,this},drawEllipse:function(e,t,n,r){var i=n*.5,s=r*.5;return this._drawingComplete=!1,this._trackSize(e,t),this._trackSize(e+n,t+r),this._pathArray=this._pathArray||[],this._pathArray.push(["M",e+i,t]),this._pathArray.push(["A",i,s,0,1,0,e+i,t+r]),this._pathArray.push(["A",i,s,0,1,0,e+i,t]),this._currentX=e,this._currentY=t,this},drawDiamond:function(e,t,n,r){var i=n*.5,s=r*.5;return this.moveTo(e+i,t),this.lineTo(e+n,t+s),this.lineTo(e+i,t+r),this.lineTo(e,t+s),this.lineTo(e+i,t),this},drawWedge:function(e,t,n,r,i,s){var o,u,a,f,l,c,h,p,d,v,m,g,y=i*2,b,w;s=s||i,this._pathType!="M"?(this._pathType="M",b=["M"],this._pathArray.push(b)):b=this._getCurrentArray(),w=this._pathArray.length-1,this._pathArray[w].push(e),this._pathArray[w].push(e),Math.abs(r)>360&&(r=360),o=Math.ceil(Math.abs(r)/45),u=r/o,a=-(u/180)*Math.PI,f=n/180*Math.PI;if(o>0){c=e+Math.cos(n/180*Math.PI)*i,h=t+Math.sin(n/180*Math.PI)*s,this._pathType="L",w++,this._pathArray[w]=["L"],this._pathArray[w].push(Math.round(c)),this._pathArray[w].push(Math.round(h)),w++,this._pathType="Q",this._pathArray[w]=["Q"];for(g=0;g<o;++g)f+=a,l=f-a/2,p=e+Math.cos(f)*i,d=t+Math.sin(f)*s,v=e+Math.cos(l)*(i/Math.cos(a/2)),m=t+Math.sin(l)*(s/Math.cos(a/2)),this._pathArray[w].push(Math.round(v)),this._pathArray[w].push(Math.round(m)),this._pathArray[w].push(Math.round(p)),this._pathArray[w].push(Math.round(d))}return this._currentX=e,this._currentY=t,this._trackSize(y,y),this},lineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!1])},relativeLineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!0])},_lineTo:function(e,t){var n=e[0],r,i,s,o,u,a,f=t?"l":"L",l=t?parseFloat(this._currentX):0,c=t?parseFloat(this._currentY):0;this._pathArray=this._pathArray||[],this._shapeType="path",i=e.length,this._pathType!==f?(this._pathType=f,o=[f],this._pathArray.push(o)):o=this._getCurrentArray(),s=this._pathArray.length-1;if(typeof n=="string"||typeof n=="number")for(r=0;r<i;r+=2)u=parseFloat(e[r]),a=parseFloat(e[r+1]),this._pathArray[s].push(u),this._pathArray[s].push(a),u+=l,a+=c,this._currentX=u,this._currentY=a,this._trackSize.apply(this,[u,a]);else for(r=0;r<i;++r)u=parseFloat(e[r][0]),a=parseFloat(e[r][1]),this._pathArray[s].push(u),this._pathArray[s].push(a),this._currentX=u,this._currentY=a,u+=l,a+=c,this._trackSize.apply(this,[u,a])},moveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!1])},relativeMoveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!0])},_moveTo:function(e,t){var n,r,i=parseFloat(e[0]),s=parseFloat(e[1]),o=t?"m":"M",u=t?parseFloat(this._currentX):0,a=t?parseFloat(this._currentY):0;this._pathArray=this._pathArray||[],this._pathType=o,r=[o],this._pathArray.push(r),n=this._pathArray.length-1,this._pathArray[n]=this._pathArray[n].concat([i,s]),i+=u,s+=a,this._currentX=i,this._currentY=s,this._trackSize(i,s)},end:function(){this._closePath()},clear:function(){this._currentX=0,this._currentY=0,this._width=0,this._height=0,this._left=0,this._right=0,this._top=0,this._bottom=0,this._pathArray=[],this._path=""},_closePath:function(){var t,n,r,i,s,o,u,a="",f=this.node,l=parseFloat(this._left),c=parseFloat(this._top),h=this.get("fill");if(this._pathArray){t=this._pathArray.concat();while(t&&t.length>0){n=t.shift(),i=n.length,r=n[0],r==="A"?a+=r+n[1]+","+n[2]:r=="z"||r=="Z"?a+=" z ":r=="C"||r=="c"?a+=r+(n[1]-l)+","+(n[2]-c):a+=" "+r+parseFloat(n[1]-l);switch(r){case"L":case"l":case"M":case"Q":case"q":for(u=2;u<i;++u)s=u%2===0?c:l,s=n[u]-s,a+=", "+parseFloat(s);break;case"A":s=" "+parseFloat(n[3])+" "+parseFloat(n[4]),s+=","+parseFloat(n[5])+" "+parseFloat(n[6]-l),s+=","+parseFloat(n[7]-c),a+=" "+s;break;case"C":case"c":for(u=3;u<i-1;u+=2)s=parseFloat(n[u]-l),s+=", ",s+=parseFloat(n[u+1]-c),a+=" "+s}}h&&h.color&&(a+="z"),e.Lang.trim(a),a&&f.setAttribute("d",a),this._path=a,this._fillChangeHandler(),this._strokeChangeHandler(),this._updateTransform()}},closePath:function(){this._pathArray.push(["z"])},_getCurrentArray:function(){var e=this._pathArray[Math.max(0,this._pathArray.length-1)];return e||(e=[],this._pathArray.push(e)),e},getBezierData:function(e,t){var n=e.length,r=[],i,s;for(i=0;i<n;++i)r[i]=[e[i][0],e[i][1]];for(s=1;s<n;++s)for(i=0;i<n-s;++i)r[i][0]=(1-t)*r[i][0]+t*r[parseInt(i+1,10)][0],r[i][1]=(1-t)*r[i][1]+t*r[parseInt(i+1,10)][1];return[r[0][0],r[0][1]]},_setCurveBoundingBox:function(e,t,n){var r,i=this._currentX,s=i,o=this._currentY,u=o,a=Math.round(Math.sqrt(t*t+n*n)),f=1/a,l;for(r=0;r<a;++r)l=this.getBezierData(e,f*r),i=isNaN(i)?l[0]:Math.min(l[0],i),s=isNaN(s)?l[0]:Math.max(l[0],s),o=isNaN(o)?l[1]:Math.min(l[1],o),u=isNaN(u)?l[1]:Math.max(l[1],u);i=Math.round(i*10)/10,s=Math.round(s*10)/10,o=Math.round(o*10)/10,u=Math.round(u*10)/10,this._trackSize(s,u),this._trackSize(i,o)},_trackSize:function(e,t){e>this._right&&(this._right=e),e<this._left&&(this._left=e),t<this._top&&(this._top=t),t>this._bottom&&(this._bottom=t),this._width=this._right-this._left,this._height=this._bottom-this._top}},e.SVGDrawing=g,f=function(t){this._transforms=[],this.matrix=new e.Matrix,this._normalizedMatrix=new e.Matrix,f.superclass.constructor.apply(this,arguments)},f.NAME="shape",e.extend(f,e.GraphicBase,e.mix({_x:0,_y:0,init:function(){this.initializer.apply(this,arguments)},initializer:function(e){var t=this,n=e.graphic,r=this.get("data");t.createNode(),n&&t._setGraphic(n),r&&t._parsePathData(r),t._updateHandler()},_setGraphic:function(t){var n;t instanceof e.SVGGraphic?this._graphic=t:(t=e.one(t),n=new e.SVGGraphic({render:t}),n._appendShape(this),this._graphic=n)},addClass:function(e){var t=this.node;t.className.baseVal=o.trim([t.className.baseVal,e].join(" "))},removeClass:function(e){var t=this.node,n=t.className.baseVal;n=n.replace(new RegExp(e+" "),e).replace(new RegExp(e),""),t.className.baseVal=n},getXY:function(){var e=this._graphic,t=e.getXY(),n=this._x,r=this._y;return[t[0]+n,t[1]+r]},setXY:function(e){var t=this._graphic,n=t.getXY();this._x=e[0]-n[0],this._y=e[1]-n[1],this.set("transform",this.get("transform"))},contains:function(t){return t===e.one(this.node)},compareTo:function(e){var t=this.node;return t===e},test:function(t){return e.Selector.test(this.node,t)},_getDefaultFill:function(){return{type:"solid",opacity:1,cx:.5,cy:.5,fx:.5,fy:.5,r:.5}},_getDefaultStroke:function(){return{weight:1,dashstyle:"none",color:"#000",opacity:1}},createNode:function(){var t=this,i=v.createElementNS("http://www.w3.org/2000/svg","svg:"+this._type),s=t.get("id"),o=t.name,u=t._camelCaseConcat,a=t.get("pointerEvents");t.node=i,t.addClass(m(r)+" "+m(u(n,r))+" "+m(o)+" "+m(u(n,o))),s&&i.setAttribute("id",s),a&&i.setAttribute("pointer-events",a),t.get("visible")||e.one(i).setStyle("visibility","hidden")},on:function(t,n){return e.Node.DOM_EVENTS[t]?e.one("#"+this.get("id")).on(t,n):e.on.apply(this,arguments)},_strokeChangeHandler:function(e){var t=this.node,n=this.get("stroke"),r,i,s,u;n&&n.weight&&n.weight>0?(u=n.linejoin||"round",r=parseFloat(n.opacity),i=n.dashstyle||"none",s=o.isArray(i)?i.toString():i,n.color=n.color||"#000000",n.weight=n.weight||1,n.opacity=o.isNumber(r)?r:1,n.linecap=n.linecap||"butt",t.setAttribute("stroke-dasharray",s),t.setAttribute("stroke",n.color),t.setAttribute("stroke-linecap",n.linecap),t.setAttribute("stroke-width",n.weight),t.setAttribute("stroke-opacity",n.opacity),u=="round"||u=="bevel"?t.setAttribute("stroke-linejoin",u):(u=parseInt(u,10),o.isNumber(u)&&(t.setAttribute("stroke-miterlimit",Math.max(u,1)),t.setAttribute("stroke-linejoin","miter")))):t.setAttribute("stroke","none")},_fillChangeHandler:function(e){var t=this.node,n=this.get("fill"),r,i;n?(i=n.type,i=="linear"||i=="radial"?(this._setGradientFill(n),t.setAttribute("fill","url(#grad"+this.get("id")+")")):n.color?(r=parseFloat(n.opacity),r=o.isNumber(r)?r:1,t.setAttribute("fill",n.color),t.setAttribute("fill-opacity",r)):t.setAttribute("fill","none")):t.setAttribute("fill","none")},_setGradientFill:function(e){var t,n,r,i,s,u=o.isNumber,a=this._graphic,f=e.type,l=a.getGradientNode("grad"+this.get("id"),f),c=e.stops,h=this.get("width"),p=this.get("height"),d=e.rotation||0,v=Math.PI/180,m=parseFloat(parseFloat(Math.tan(d*v)).toFixed(8)),g,y,b,w,E="0%",S="100%",x="0%",T="0%",N=e.cx,C=e.cy,k=e.fx,L=e.fy,A=e.r,O=[];f=="linear"?(N=h/2,C=p/2,Math.abs(m)*h/2>=p/2?(d<180?(x=0,T=p):(x=p,T=0),E=N-(C-x)/m,S=N-(C-T)/m):(d>90&&d<270?(E=h,S=0):(E=0,S=h),x=(m*(N-E)-C)*-1,T=(m*(N-S)-C)*-1),E=Math.round(100*E/h),S=Math.round(100*S/h),x=Math.round(100*x/p),T=Math.round(100*T/p),E=u(E)?E:0,S=u(S)?S:100,x=u(x)?x:0,T=u(T)?T:0,l.setAttribute("spreadMethod","pad"),l.setAttribute("width",h),l.setAttribute("height",p),l.setAttribute("x1",E+"%"),l.setAttribute("x2",S+"%"),l.setAttribute("y1",x+"%"),l.setAttribute("y2",T+"%")):(l.setAttribute("cx",N*100+"%"),l.setAttribute("cy",C*100+"%"),l.setAttribute("fx",k*100+"%"),l.setAttribute("fy",L*100+"%"),l.setAttribute("r",A*100+"%")),y=c.length,b=0;for(g=0;g<y;++g)this._stops&&this._stops.length>0?(i=this._stops.shift(),s=!1):(i=a._createGraphicNode("stop"),s=!0),w=c[g],n=w.opacity,r=w.color,t=w.offset||g/(y-1),t=Math.round(t*100)+"%",n=u(n)?n:1,n=Math.max(0,Math.min(1,n)),b=(g+1)/y,i.setAttribute("offset",t),i.setAttribute("stop-color",r),i.setAttribute("stop-opacity",n),s&&l.appendChild(i),O.push(i);while(this._stops&&this._stops.length>0)l.removeChild(this._stops.shift());this._stops=O},_stops:null,set:function(){var e=this;u.prototype.set.apply(e,arguments),e.initialized&&e._updateHandler()},translate:function(e,t){this._addTransform("translate",arguments)},translateX:function(e){this._addTransform("translateX",arguments)},translateY:function(e){this._addTransform("translateY",arguments)},skew:function(e,t){this._addTransform("skew",arguments)},skewX:function(e){this._addTransform("skewX",arguments)},skewY:function(e){this._addTransform("skewY",arguments)},rotate:function(e){this._addTransform("rotate",arguments)},scale:function(e,t){this._addTransform("scale",arguments)},_addTransform:function(t,n){n=e.Array(n),this._transform=o.trim(this._transform+" "+t+"("+n.join(", ")+")"),n.unshift(t),this._transforms.push(n),this.initialized&&this._updateTransform()},_updateTransform:function(){var t=this._type=="path",n=this.node,r,i,s,o,u,a,f,l=this.matrix,c=this._normalizedMatrix,h,p=this._transforms.length;if(t||this._transforms&&this._transforms.length>0){o=this._x,u=this._y,s=this.get("transformOrigin"),a=o+s[0]*this.get("width"),f=u+s[1]*this.get("height"),t&&(this instanceof e.SVGPath||(a=this._left+s[0]*this.get("width"),f=this._top+s[1]*this.get("height")),c.init({dx:o+this._left,dy:u+this._top})),c.translate(a,f);for(h=0;h<p;++h)r=this._transforms[h].shift(),r&&(c[r].apply(c,this._transforms[h]),l[r].apply(l,this._transforms[h])),t&&this._transforms[h].unshift(r);c.translate(-a,-f),i="matrix("+c.a+","+c.b+","+c.c+","+c.d+","+c.dx+","+c.dy+")"}this._graphic.addToRedrawQueue(this),i&&n.setAttribute("transform",i),t||(this._transforms=[])},_draw:function(){var e=this.node;e.setAttribute("width",this.get("width")),e.setAttribute("height",this.get("height")),e.setAttribute("x",this._x),e.setAttribute("y",this._y),e.style.left=this._x+"px",e.style.top=this._y+"px",this._fillChangeHandler(),this._strokeChangeHandler(),this._updateTransform()},_updateHandler:function(e){this._draw()},_transform:"",getBounds:function(){var e=this._type,t=this.get("stroke"),n=this.get("width"),r=this.get("height"),i=e=="path"?0:this._x,s=e=="path"?0:this._y,o=0;return e!="path"&&(t&&t.weight&&(o=t.weight),n=i+n+o-(i-o),r=s+r+o-(s-o),i-=o,s-=o),this._normalizedMatrix.getContentRect(n,r,i,s)},toFront:function(){var e=this.get("graphic");e&&e._toFront(this)},toBack:function(){var e=this.get("graphic");e&&e._toBack(this)},_parsePathData:function(t){var n,r,o,u=e.Lang.trim(t.match(i)),a,f,l,c=this._pathSymbolToMethod;if(u){this.clear(),f=u.length||0;for(a=0;a<f;a+=1)l=u[a],r=l.substr(0,1),o=l.substr(1).match(s),n=c[r],n&&(o?this[n].apply(this,o):this[n].apply(this));this.end()}},destroy:function(){var e=this.get("graphic");e?e.removeShape(this):this._destroy()},_destroy:function(){this.node&&(e.Event.purgeElement(this.node,!0),this.node.parentNode&&this.node.parentNode.removeChild(this.node),this.node=null)}},e.SVGDrawing.prototype)),f.ATTRS={transformOrigin:{valueFn:function(){return[.5,.5]}},transform:{setter:function(e){return this.matrix.init(),this._normalizedMatrix.init(),this._transforms=this.matrix.getTransformArray(e),this._transform=e,e},getter:function(){return this._transform}},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this.node;return t&&t.setAttribute("id",e),e}},x:{getter:function(){return this._x},setter:function(e){var t=this.get("transform");this._x=e,t&&this.set("transform",t)}},y:{getter:function(){return this._y},setter:function(e){var t=this.get("transform");this._y=e,t&&this.set("transform",t)}},width:{value:0},height:{value:0},visible:{value:!0,setter:function(e){var t=e?"visible":"hidden";return this.node&&(this.node.style.visibility=t),e}},fill:{valueFn:"_getDefaultFill",setter:function(t){var n,r=this.get("fill")||this._getDefaultFill();return n=t?e.merge(r,t):null,n&&n.color&&(n.color===undefined||n.color=="none")&&(n.color=null),n}},stroke:{valueFn:"_getDefaultStroke",setter:function(t){var n=this.get("stroke")||this._getDefaultStroke(),r;return t&&t.hasOwnProperty("weight")&&(r=parseInt(t.weight,10),isNaN(r)||(t.weight=r)),t?e.merge(n,t):null}},pointerEvents:{valueFn:function(){var e="visiblePainted",t=this.node;return t&&t.setAttribute("pointer-events",e),e},setter:function(e){var t=this.node;return t&&t.setAttribute("pointer-events",e),e}},node:{readOnly:!0,getter:function(){return this.node}},data:{setter:function(e){return this.get("node")&&this._parsePathData(e),e}},graphic:{readOnly:!0,getter:function(){return this._graphic}}},e.SVGShape=f,h=function(e){h.superclass.constructor.apply(this,arguments)},h.NAME="path",e.extend(h,e.SVGShape,{_left:0,_right:0,_top:0,_bottom:0,_type:"path",_path:""}),h.ATTRS=e.merge(e.SVGShape.ATTRS,{path:{readOnly:!0,getter:function(){return this._path}},width:{getter:function(){var e=Math.max(this._right-this._left,0);return e}},height:{getter:function(){return Math.max(this._bottom-this._top,0)}}}),e.SVGPath=h,c=function(){c.superclass.constructor.apply(this,arguments)},c.NAME="rect",e.extend(c,e.SVGShape,{_type:"rect"}),c.ATTRS=e.SVGShape.ATTRS,e.SVGRect=c,p=function(e){p.superclass.constructor.apply(this,arguments)},p.NAME="ellipse",e.extend(p,f,{_type:"ellipse",_draw:function(){var e=this.node,t=this.get("width"),n=this.get("height"),r=this.get("x"),i=this.get("y"),s=t*.5,o=n*.5,u=r+s,a=i+o;e.setAttribute("rx",s),e.setAttribute("ry",o),e.setAttribute("cx",u),e.setAttribute("cy",a),this._fillChangeHandler(),this._strokeChangeHandler(),this._updateTransform()}}),p.ATTRS=e.merge(f.ATTRS,{xRadius:{setter:function(e){this.set("width",e*2)},getter:function(){var e=this.get("width");return e&&(e*=.5),e}},yRadius:{setter:function(e){this.set("height",e*2)},getter:function(){var e=this.get("height");return e&&(e*=.5),e}}}),e.SVGEllipse=p,l=function(e){l.superclass.constructor.apply(this,arguments)},l.NAME="circle",e.extend(l,e.SVGShape,{_type:"circle",_draw:function(){var e=this.node,t=this.get("x"),n=this.get("y"),r=this.get("radius"),i=t+r,s=n+r;e.setAttribute("r",r),e.setAttribute("cx",i),e.setAttribute("cy",s),this._fillChangeHandler(),this._strokeChangeHandler(),this._updateTransform()}}),l.ATTRS=e.merge(e.SVGShape.ATTRS,{width:{setter:function(e){return this.set("radius",e/2),e},getter:function(){return this.get("radius")*2}},height:{setter:function(e){return this.set("radius",e/2),e},getter:function(){return this.get("radius")*2}},radius:{value:0}}),e.SVGCircle=l,d=function(){d.superclass.constructor.apply(this,arguments)},d.NAME="svgPieSlice",e.extend(d,e.SVGShape,e.mix({_type:"path",_draw:function(e){var t=this.get("cx"),n=this.get("cy"),r=this.get("startAngle"),i=this.get("arc"),s=this.get("radius");this.clear(),this.drawWedge(t,n,r,i,s),this.end()}},e.SVGDrawing.prototype)),d.ATTRS=e.mix({cx:{value:0},cy:{value:0},startAngle:{value:0},arc:{value:0},radius:{value:0}},e.SVGShape.ATTRS),e.SVGPieSlice=d,a=function(e){a.superclass.constructor.apply(this,arguments)},a.NAME="svgGraphic",a.ATTRS={render:{},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this._node;return t&&t.setAttribute("id",e),e}},shapes:{readOnly:!0,getter:function(){return this._shapes}},contentBounds:{readOnly:!0,getter:function(){return this._contentBounds}},node:{readOnly:!0,getter:function(){return this._node}},width:{setter:function(e){return this._node&&(this._node.style.width=e+"px"),e}},height:{setter:function(e){return this._node&&(this._node.style.height=e+"px"),e}},autoSize:{value:!1},preserveAspectRatio:{value:"xMidYMid"},resizeDown:{value:!1},x:{getter:function(){return this._x},setter:function(e){return this._x=e,this._node&&(this._node.style.left=e+"px"),e}},y:{getter:function(){return this._y},setter:function(e){return this._y=e,this._node&&(this._node.style.top=e+"px"),e}},autoDraw:{value:!0},visible:{value:!0,setter:function(e){return this._toggleVisible(e),e}},pointerEvents:{value:"none"}},e.extend(a,e.GraphicBase,{set:function(t,n){var r=this,i={autoDraw:!0,autoSize:!0,preserveAspectRatio:!0,resizeDown:!0},s,a=!1;u.prototype.set.apply(r,arguments);if(r._state.autoDraw===!0&&e.Object.size(this._shapes)>0)if(o.isString&&i[t])a=!0;else if(o.isObject(t))for(s in i)if(i.hasOwnProperty(s)&&t[s]){a=!0;break}a&&r._redraw()},_x:0,_y:0,getXY:function(){var t=e.one(this._node),n;return t&&(n=t.getXY()),n},initializer:function(){var e=this.get("render"),t=this.get("visible")?"visible":"hidden";this._shapes={},this._contentBounds={left:0,top:0,right:0,bottom:0},this._gradients={},this._node=v.createElement("div"),this._node.style.position="absolute",this._node.style.left=this.get("x")+"px",this._node.style.top=this.get("y")+"px",this._node.style.visibility=t,this._contentNode=this._createGraphics(),this._contentNode.style.visibility=t,this._contentNode.setAttribute("id",this.get("id")),this._node.appendChild(this._contentNode),e&&this.render(e)},render:function(t){var n=e.one(t),r=this.get("width")||parseInt(n.getComputedStyle("width"),10),i=this.get("height")||parseInt(n.getComputedStyle("height"),10);return n=n||e.one(v.body),n.append(this._node),this.parentNode=n,this.set("width",r),this.set("height",i),this},destroy:function(){this.removeAllShapes(),this._contentNode&&(this._removeChildren(this._contentNode),this._contentNode.parentNode&&this._contentNode.parentNode.removeChild(this._contentNode),this._contentNode=null),this._node&&(this._removeChildren(this._node),e.one(this._node).remove(!0),this._node=null)},addShape:function(e){e.graphic=this,this.get("visible")||(e.visible=!1);var t=this._getShapeClass(e.type),n=new t(e);return this._appendShape(n),n},_appendShape:function(e){var t=e.node,n=this._frag||this._contentNode;this.get("autoDraw")?n.appendChild(t):this._getDocFrag().appendChild(t)},removeShape:function(e){return e instanceof f||o.isString(e)&&(e=this._shapes[e]),e&&e instanceof f&&(e._destroy(),delete this._shapes[e.get("id")]),this.get("autoDraw")&&this._redraw(),e},removeAllShapes:function(){var e=this._shapes,t;for(t in e)e.hasOwnProperty(t)&&e[t]._destroy();this._shapes={}},_removeChildren:function(e){if(e.hasChildNodes()){var t;while(e.firstChild)t=e.firstChild,this._removeChildren(t),e.removeChild(t)}},clear:function(){this.removeAllShapes()},_toggleVisible:function(e){var t,n=this._shapes,r=e?"visible":"hidden";if(n)for(t in n)n.hasOwnProperty(t)&&n[t].set("visible",e);this._contentNode&&(this._contentNode.style.visibility=r),this._node&&(this._node.style.visibility=r)},_getShapeClass:function(e){var t=this._shapeClass[e];return t?t:e},_shapeClass:{circle:e.SVGCircle,rect:e.SVGRect,path:e.SVGPath,ellipse:e.SVGEllipse,pieslice:e.SVGPieSlice},getShapeById:function(e){var t=this._shapes[e];return t},batch:function(e){var t=this.get("autoDraw");this.set("autoDraw",!1),e(),this.set("autoDraw",t)},_getDocFrag:function(){return this._frag||(this._frag=v.createDocumentFragment()),this._frag},_redraw:function(){var t=this.get("autoSize"),n=this.get("preserveAspectRatio"),r=this.get("resizeDown")?this._getUpdatedContentBounds():this._contentBounds,i=r.left,s=r.right,o=r.top,u=r.bottom,a=s-i,f=u-o,l,c,h,p,d;t?t=="sizeContentToGraphic"?(d=e.one(this._node),l=parseFloat(d.getComputedStyle("width")),c=parseFloat(d.getComputedStyle("height")),h=p=0,this._contentNode.setAttribute("preserveAspectRatio",n)):(l=a,c=f,h=i,p=o,this._state.width=a,this._state.height=f,this._node&&(this._node.style.width=a+"px",this._node.style.height=f+"px")):(l=a,c=f,h=i,p=o),this._contentNode&&(this._contentNode.style.left=h+"px",this._contentNode.style.top=p+"px",this._contentNode.setAttribute("width",l),this._contentNode.setAttribute("height",c),this._contentNode.style.width=l+"px",this._contentNode.style.height=c+"px",this._contentNode.setAttribute("viewBox",""+i+" "+o+" "+a+" "+f+"")),this._frag&&(this._contentNode&&this._contentNode.appendChild(this._frag),this._frag=null)},addToRedrawQueue:function(e){var t,n;this._shapes[e.get("id")]=e,this.get("resizeDown")||(t=e.getBounds(),n=this._contentBounds,n.left=n.left<t.left?n.left:t.left,n.top=n.top<t.top?n.top:t.top,n.right=n.right>t.right?n.right:t.right,n.bottom=n.bottom>t.bottom?n.bottom:t.bottom,n.width=n.right-n.left,n.height=n.bottom-n.top,this._contentBounds=n),this.get("autoDraw")&&this._redraw()},_getUpdatedContentBounds:function(){var e,t,n,r=this._shapes,i={};for(t in r)r.hasOwnProperty(t)&&(n=r[t],e=n.getBounds(),i.left=o.isNumber(i.left)?Math.min(i.left,e.left):e.left,i.top=o.isNumber(i.top)?Math.min(i.top,e.top):e.top,i.right=o.isNumber(i.right)?Math.max(i.right,e.right):e.right,i.bottom=o.isNumber(i.bottom)?Math.max(i.bottom,e.bottom):e.bottom);return i.left=o.isNumber(i.left)?i.left:0,i.top=o.isNumber(i.top)?i.top:0,i.right=o.isNumber(i.right)?i.right:0,i.bottom=o.isNumber(i.bottom)?i.bottom:0,this._contentBounds=i,i},_createGraphics:function(){var e=this._createGraphicNode("svg"),t=this.get("pointerEvents");return e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.style.overflow="auto",e.setAttribute("overflow","auto"),e.setAttribute("pointer-events",t),e},_createGraphicNode:function(e,t){var n=v.createElementNS("http://www.w3.org/2000/svg","svg:"+e),r=t||"none";return e!=="defs"&&e!=="stop"&&e!=="linearGradient"&&e!="radialGradient"&&n.setAttribute("pointer-events",r),n},getGradientNode:function(e,t){var n=this._gradients,r,i=t+"Gradient";return n.hasOwnProperty(e)&&n[e].tagName.indexOf(t)>-1?r=this._gradients[e]:(r=this._createGraphicNode(i),this._defs||(this._defs=this._createGraphicNode("defs"),this._contentNode.appendChild(this._defs)),this._defs.appendChild(r),e=e||"gradient"+Math.round(1e5*Math.random()),r.setAttribute("id",e),n.hasOwnProperty(e)&&this._defs.removeChild(n[e]),n[e]=r),r},_toFront:function(t){var n=this._contentNode;t instanceof e.SVGShape&&(t=t.get("node")),n&&t&&n.appendChild(t)},_toBack:function(t){var n=this._contentNode,r;t instanceof e.SVGShape&&(t=t.get("node")),n&&t&&(r=n.firstChild,r?n.insertBefore(t,r):n.appendChild(t))}}),e.SVGGraphic=a},"3.7.3",{requires:["graphics"]});
diff --git a/js/yui3/graphics-vml-default/graphics-vml-default-min.js b/js/yui3/graphics-vml-default/graphics-vml-default-min.js
new file mode 100644
index 000000000..6d977ddc1
--- /dev/null
+++ b/js/yui3/graphics-vml-default/graphics-vml-default-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-vml-default",function(e,t){e.Graphic=e.VMLGraphic,e.Shape=e.VMLShape,e.Circle=e.VMLCircle,e.Rect=e.VMLRect,e.Ellipse=e.VMLEllipse,e.Path=e.VMLPath,e.Drawing=e.VMLDrawing},"3.7.3");
diff --git a/js/yui3/graphics-vml/graphics-vml-min.js b/js/yui3/graphics-vml/graphics-vml-min.js
new file mode 100644
index 000000000..831f25293
--- /dev/null
+++ b/js/yui3/graphics-vml/graphics-vml-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics-vml",function(e,t){function S(){}var n="vml",r="shape",i=/[a-z][^a-z]*/ig,s=/[-]?[0-9]*[0-9|\.][0-9]*/g,o=e.Lang,u=o.isNumber,a=o.isArray,f=o.isString,l=e.DOM,c=e.Selector,h=e.config.doc,p=e.AttributeLite,d,v,m,g,y,b,w,E=e.ClassNameManager.getClassName;S.prototype={_pathSymbolToMethod:{M:"moveTo",m:"relativeMoveTo",L:"lineTo",l:"relativeLineTo",C:"curveTo",c:"relativeCurveTo",Q:"quadraticCurveTo",q:"relativeQuadraticCurveTo",z:"closePath",Z:"closePath"},_coordSpaceMultiplier:100,_round:function(e){return Math.round(e*this._coordSpaceMultiplier)},_addToPath:function(e){this._path=this._path||"",this._movePath&&(this._path+=this._movePath,this._movePath=null),this._path+=e},_currentX:0,_currentY:0,curveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!1])},relativeCurveTo:function(){this._curveTo.apply(this,[e.Array(arguments),!0])},_curveTo:function(e,t){var n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y=t?" v ":" c ",b=t?parseFloat(this._currentX):0,w=t?parseFloat(this._currentY):0;m=e.length-5,g=y;for(v=0;v<m;v+=6)o=parseFloat(e[v]),u=parseFloat(e[v+1]),a=parseFloat(e[v+2]),f=parseFloat(e[v+3]),i=parseFloat(e[v+4]),s=parseFloat(e[v+5]),v>0&&(g+=", "),g=g+this._round(o)+", "+this._round(u)+", "+this._round(a)+", "+this._round(f)+", "+this._round(i)+", "+this._round(s),o+=b,u+=w,a+=b,f+=w,i+=b,s+=w,c=Math.max(i,Math.max(o,a)),p=Math.max(s,Math.max(u,f)),h=Math.min(i,Math.min(o,a)),d=Math.min(s,Math.min(u,f)),n=Math.abs(c-h),r=Math.abs(p-d),l=[[this._currentX,this._currentY],[o,u],[a,f],[i,s]],this._setCurveBoundingBox(l,n,r),this._currentX=i,this._currentY=s;this._addToPath(g)},quadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!1])},relativeQuadraticCurveTo:function(){this._quadraticCurveTo.apply(this,[e.Array(arguments),!0])},_quadraticCurveTo:function(e,t){var n,r,i,s,o,u,a,f,l=this._currentX,c=this._currentY,h,p=e.length-3,d=[],v=t?parseFloat(this._currentX):0,m=t?parseFloat(this._currentY):0;for(h=0;h<p;h+=4)n=parseFloat(e[h])+v,r=parseFloat(e[h+1])+m,a=parseFloat(e[h+2])+v,f=parseFloat(e[h+3])+m,i=l+.67*(n-l),s=c+.67*(r-c),o=i+(a-l)*.34,u=s+(f-c)*.34,d.push(i),d.push(s),d.push(o),d.push(u),d.push(a),d.push(f);this._curveTo.apply(this,[d,!1])},drawRect:function(e,t,n,r){return this.moveTo(e,t),this.lineTo(e+n,t),this.lineTo(e+n,t+r),this.lineTo(e,t+r),this.lineTo(e,t),this._currentX=e,this._currentY=t,this},drawRoundRect:function(e,t,n,r,i,s){return this.moveTo(e,t+s),this.lineTo(e,t+r-s),this.quadraticCurveTo(e,t+r,e+i,t+r),this.lineTo(e+n-i,t+r),this.quadraticCurveTo(e+n,t+r,e+n,t+r-s),this.lineTo(e+n,t+s),this.quadraticCurveTo(e+n,t,e+n-i,t),this.lineTo(e+i,t),this.quadraticCurveTo(e,t,e,t+s),this},drawCircle:function(e,t,n){var r=0,i=360,s=n*2;return i*=65535,this._drawingComplete=!1,this._trackSize(e+s,t+s),this.moveTo(e+s,t+n),this._addToPath(" ae "+this._round(e+n)+", "+this._round(t+n)+", "+this._round(n)+", "+this._round(n)+", "+r+", "+i),this},drawEllipse:function(e,t,n,r){var i=0,s=360,o=n*.5,u=r*.5;return s*=65535,this._drawingComplete=!1,this._trackSize(e+n,t+r),this.moveTo(e+n,t+u),this._addToPath(" ae "+this._round(e+o)+", "+this._round(e+o)+", "+this._round(t+u)+", "+this._round(o)+", "+this._round(u)+", "+i+", "+s),this},drawDiamond:function(e,t,n,r){var i=n*.5,s=r*.5;return this.moveTo(e+i,t),this.lineTo(e+n,t+s),this.lineTo(e+i,t+r),this.lineTo(e,t+s),this.lineTo(e+i,t),this},drawWedge:function(e,t,n,r,i){var s=i*2;return Math.abs(r)>360&&(r=360),this._currentX=e,this._currentY=t,n*=-65535,r*=65536,n=Math.round(n),r=Math.round(r),this.moveTo(e,t),this._addToPath(" ae "+this._round(e)+", "+this._round(t)+", "+this._round(i)+" "+this._round(i)+", "+n+", "+r),this._trackSize(s,s),this},lineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!1])},relativeLineTo:function(){this._lineTo.apply(this,[e.Array(arguments),!0])},_lineTo:function(e,t){var n=e[0],r,i,s,o,u=t?" r ":" l ",a=t?parseFloat(this._currentX):0,f=t?parseFloat(this._currentY):0;if(typeof n=="string"||typeof n=="number"){i=e.length-1;for(r=0;r<i;r+=2)s=parseFloat(e[r]),o=parseFloat(e[r+1]),u+=" "+this._round(s)+", "+this._round(o),s+=a,o+=f,this._currentX=s,this._currentY=o,this._trackSize.apply(this,[s,o])}else{i=e.length;for(r=0;r<i;r+=1)s=parseFloat(e[r][0]),o=parseFloat(e[r][1]),u+=" "+this._round(s)+", "+this._round(o),s+=a,o+=f,this._currentX=s,this._currentY=o,this._trackSize.apply(this,[s,o])}return this._addToPath(u),this},moveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!1])},relativeMoveTo:function(){this._moveTo.apply(this,[e.Array(arguments),!0])},_moveTo:function(e,t){var n=parseFloat(e[0]),r=parseFloat(e[1]),i=t?" t ":" m ",s=t?parseFloat(this._currentX):0,o=t?parseFloat(this._currentY):0;this._movePath=i+this._round(n)+", "+this._round(r),n+=s,r+=o,this._trackSize(n,r),this._currentX=n,this._currentY=r},_closePath:function(){var e=this.get("fill"),t=this.get("stroke"),n=this.node,r=this.get("width"),i=this.get("height"),s=this._path,o="",u=this._coordSpaceMultiplier;this._fillChangeHandler(),this._strokeChangeHandler(),s&&(e&&e.color&&(o+=" x"),t&&(o+=" e")),s&&(n.path=s+o),!isNaN(r)&&!isNaN(i)&&(n.coordOrigin=this._left+", "+this._top,n.coordSize=r*u+", "+i*u,n.style.position="absolute",n.style.width=r+"px",n.style.height=i+"px"),this._path=s,this._movePath=null,this._updateTransform()},end:function(){this._closePath()},closePath:function(){this._addToPath(" x e")},clear:function(){this._right=0,this._bottom=0,this._width=0,this._height=0,this._left=0,this._top=0,this._path="",this._movePath=null},getBezierData:function(e,t){var n=e.length,r=[],i,s;for(i=0;i<n;++i)r[i]=[e[i][0],e[i][1]];for(s=1;s<n;++s)for(i=0;i<n-s;++i)r[i][0]=(1-t)*r[i][0]+t*r[parseInt(i+1,10)][0],r[i][1]=(1-t)*r[i][1]+t*r[parseInt(i+1,10)][1];return[r[0][0],r[0][1]]},_setCurveBoundingBox:function(e,t,n){var r,i=this._currentX,s=i,o=this._currentY,u=o,a=Math.round(Math.sqrt(t*t+n*n)),f=1/a,l;for(r=0;r<a;++r)l=this.getBezierData(e,f*r),i=isNaN(i)?l[0]:Math.min(l[0],i),s=isNaN(s)?l[0]:Math.max(l[0],s),o=isNaN(o)?l[1]:Math.min(l[1],o),u=isNaN(u)?l[1]:Math.max(l[1],u);i=Math.round(i*10)/10,s=Math.round(s*10)/10,o=Math.round(o*10)/10,u=Math.round(u*10)/10,this._trackSize(s,u),this._trackSize(i,o)},_trackSize:function(e,t){e>this._right&&(this._right=e),e<this._left&&(this._left=e),t<this._top&&(this._top=t),t>this._bottom&&(this._bottom=t),this._width=this._right-this._left,this._height=this._bottom-this._top},_left:0,_right:0,_top:0,_bottom:0,_width:0,_height:0},e.VMLDrawing=S,d=function(){this._transforms=[],this.matrix=new e.Matrix,this._normalizedMatrix=new e.Matrix,d.superclass.constructor.apply(this,arguments)},d.NAME="shape",e.extend(d,e.GraphicBase,e.mix({_type:"shape",init:function(){this.initializer.apply(this,arguments)},initializer:function(e){var t=this,n=e.graphic,r=this.get("data");t.createNode(),n&&this._setGraphic(n),r&&t._parsePathData(r),this._updateHandler()},_setGraphic:function(t){var n;t instanceof e.VMLGraphic?this._graphic=t:(t=e.one(t),n=new e.VMLGraphic({render:t}),n._appendShape(this),this._graphic=n,this._appendStrokeAndFill())},_appendStrokeAndFill:function(){this._strokeNode&&this.node.appendChild(this._strokeNode),this._fillNode&&this.node.appendChild(this._fillNode)},createNode:function(){var e,t=this._camelCaseConcat,i=this.get("x"),s=this.get("y"),o=this.get("width"),u=this.get("height"),a,f,l=this.name,c,p=this.get("visible")?"visible":"hidden",d,v,m,g,y,b,w,S,x,T;a=this.get("id"),f=this._type=="path"?"shape":this._type,v=E(r)+" "+E(t(n,r))+" "+E(l)+" "+E(t(n,l))+" "+n+f,m=this._getStrokeProps(),x=this._getFillProps(),c="<"+f+' xmlns="urn:schemas-microsft.com:vml" id="'+a+'" class="'+v+'" style="behavior:url(#default#VML);display:inline-block;position:absolute;left:'+i+"px;top:"+s+"px;width:"+o+"px;height:"+u+"px;visibility:"+p+'"',m&&m.weight&&m.weight>0?(g=m.endcap,y=parseFloat(m.opacity),b=m.joinstyle,w=m.miterlimit,S=m.dashstyle,c+=' stroked="t" strokecolor="'+m.color+'" strokeWeight="'+m.weight+'px"',d='<stroke class="vmlstroke" xmlns="urn:schemas-microsft.com:vml" on="t" style="behavior:url(#default#VML);display:inline-block;"',d+=' opacity="'+y+'"',g&&(d+=' endcap="'+g+'"'),b&&(d+=' joinstyle="'+b+'"'),w&&(d+=' miterlimit="'+w+'"'),S&&(d+=' dashstyle="'+S+'"'),d+="></stroke>",this._strokeNode=h.createElement(d),c+=' stroked="t"'):c+=' stroked="f"',x&&(x.node&&(T=x.node,this._fillNode=h.createElement(T)),x.color&&(c+=' fillcolor="'+x.color+'"'),c+=' filled="'+x.filled+'"'),c+=">",c+="</"+f+">",e=h.createElement(c),this.node=e,this._strokeFlag=!1,this._fillFlag=!1},addClass:function(e){var t=this.node;l.addClass(t,e)},removeClass:function(e){var t=this.node;l.removeClass(t,e)},getXY:function(){var e=this._graphic,t=e.getXY(),n=this.get("x"),r=this.get("y");return[t[0]+n,t[1]+r]},setXY:function(e){var t=this._graphic,n=t.getXY();this.set("x",e[0]-n[0]),this.set("y",e[1]-n[1])},contains:function(t){return t===e.one(this.node)},compareTo:function(e){var t=this.node;return t===e},test:function(e){return c.test(this.node,e)},_getStrokeProps:function(){var e,t=this.get("stroke"),n,r,i="",s,o=0,f,l,c;if(t&&t.weight&&t.weight>0){e={},l=t.linecap||"flat",c=t.linejoin||"round",l!="round"&&l!="square"&&(l="flat"),n=parseFloat(t.opacity),r=t.dashstyle||"none",t.color=t.color||"#000000",t.weight=t.weight||1,t.opacity=u(n)?n:1,e.stroked=!0,e.color=t.color,e.weight=t.weight,e.endcap=l,e.opacity=t.opacity;if(a(r)){i=[],f=r.length;for(o=0;o<f;++o)s=r[o],i[o]=s/t.weight}c=="round"||c=="bevel"?e.joinstyle=c:(c=parseInt(c,10),u(c)&&(e.miterlimit=Math.max(c,1),e.joinstyle="miter")),e.dashstyle=i}return e},_strokeChangeHandler:function(e){if(!this._strokeFlag)return;var t=this.node,n=this.get("stroke"),r,i,s="",o,f=0,l,c,h;if(n&&n.weight&&n.weight>0){c=n.linecap||"flat",h=n.linejoin||"round",c!="round"&&c!="square"&&(c="flat"),r=parseFloat(n.opacity),i=n.dashstyle||"none",n.color=n.color||"#000000",n.weight=n.weight||1,n.opacity=u(r)?r:1,t.stroked=!0,t.strokeColor=n.color,t.strokeWeight=n.weight+"px",this._strokeNode||(this._strokeNode=this._createGraphicNode("stroke"),t.appendChild(this._strokeNode)),this._strokeNode.endcap=c,this._strokeNode.opacity=n.opacity;if(a(i)){s=[],l=i.length;for(f=0;f<l;++f)o=i[f],s[f]=o/n.weight}h=="round"||h=="bevel"?this._strokeNode.joinstyle=h:(h=parseInt(h,10),u(h)&&(this._strokeNode.miterlimit=Math.max(h,1),this._strokeNode.joinstyle="miter")),this._strokeNode.dashstyle=s,this._strokeNode.on=!0}else this._strokeNode&&(this._strokeNode.on=!1),t.stroked=!1;this._strokeFlag=!1},_getFillProps:function(){var e=this.get("fill"),t,n,r,i,s,o=!1;if(e){n={};if(e.type=="radial"||e.type=="linear"){t=parseFloat(e.opacity),t=u(t)?t:1,o=!0,r=this._getGradientFill(e),s='<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" opacity="'+t+'"';for(i in r)r.hasOwnProperty(i)&&(s+=" "+i+'="'+r[i]+'"');s+=" />",n.node=s}else e.color&&(t=parseFloat(e.opacity),o=!0,n.color=e.color,u(t)&&(t=Math.max(Math.min(t,1),0),n.opacity=t,t<1&&(n.node='<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" type="solid" opacity="'+t+'"/>')));n.filled=o}return n},_fillChangeHandler:function(e){if(!this._fillFlag)return;var t=this.node,n=this.get("fill"),r,i,s=!1,o,a;if(n)if(n.type=="radial"||n.type=="linear"){s=!0,a=this._getGradientFill(n);if(this._fillNode)for(o in a)a.hasOwnProperty(o)&&(o=="colors"?this._fillNode.colors.value=a[o]:this._fillNode[o]=a[o]);else{i='<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;"';for(o in a)a.hasOwnProperty(o)&&(i+=" "+o+'="'+a[o]+'"');i+=" />",this._fillNode=h.createElement(i),t.appendChild(this._fillNode)}}else n.color&&(t.fillcolor=n.color,r=parseFloat(n.opacity),s=!0,u(r)&&r<1?(n.opacity=r,this._fillNode?(this._fillNode.getAttribute("type")!="solid"&&(this._fillNode.type="solid"),this._fillNode.opacity=r):(i='<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" type="solid" opacity="'+r+'"/>',this._fillNode=h.createElement(i),t.appendChild(this._fillNode))):this._fillNode&&(this._fillNode.opacity=1,this._fillNode.type="solid"));t.filled=s,this._fillFlag=!1},_updateFillNode:function(e){this._fillNode||(this._fillNode=this._createGraphicNode("fill"),e.appendChild(this._fillNode))},_getGradientFill:function(e){var t={},n,r,i=e.type,s=this.get("width"),o=this.get("height"),a=u,f,l=e.stops,c=l.length,h,p,d,v,m="",g=e.cx,y=e.cy,b=e.fx,w=e.fy,E=e.r,S,x=e.rotation||0;i==="linear"?(x<=270?x=Math.abs(x-270):x<360?x=270+(360-x):x=270,t.type="gradient",t.angle=x):i==="radial"&&(n=s*E*2,r=o*E*2,b=E*2*(b-.5),w=E*2*(w-.5),b+=g,w+=y,t.focussize=n/s/10+"% "+r/o/10+"%",t.alignshape=!1,t.type="gradientradial",t.focus="100%",t.focusposition=Math.round(b*100)+"% "+Math.round(w*100)+"%");for(d=0;d<c;++d)f=l[d],p=f.color,h=f.opacity,h=a(h)?h:1,S=f.offset||d/(c-1),S*=E*2,S=Math.round(100*S)+"%",v=d>0?d+1:"",t["opacity"+v]=h+"",m+=", "+S+" "+p;return parseFloat(S)<100&&(m+=", 100% "+p),t.colors=m.substr(2),t},_addTransform:function(t,n){n=e.Array(n),this._transform=o.trim(this._transform+" "+t+"("+n.join(", ")+")"),n.unshift(t),this._transforms.push(n),this.initialized&&this._updateTransform()},_updateTransform:function(){var t=this.node,n,r,i,s=this.get("x"),o=this.get("y"),u,a,f=this.matrix,l=this._normalizedMatrix,c=this instanceof e.VMLPath,p,d=this._transforms.length;if(this._transforms&&this._transforms.length>0){i=this.get("transformOrigin"),c&&l.translate(this._left,this._top),u=i[0]-.5,a=i[1]-.5,u=Math.max(-0.5,Math.min(.5,u)),a=Math.max(-0.5,Math.min(.5,a));for(p=0;p<d;++p)n=this._transforms[p].shift(),n&&(l[n].apply(l,this._transforms[p]),f[n].apply(f,this._transforms[p]));c&&l.translate(-this._left,-this._top),r=l.a+","+l.c+","+l.b+","+l.d+","+0+","+0}this._graphic.addToRedrawQueue(this),r&&(this._skew||(this._skew=h.createElement('<skew class="vmlskew" xmlns="urn:schemas-microsft.com:vml" on="false" style="behavior:url(#default#VML);display:inline-block;" />'),this.node.appendChild(this._skew)),this._skew.matrix=r,this._skew.on=!0,this._skew.origin=u+", "+a),this._type!="path"&&(this._transforms=[]),t.style.left=s+this._getSkewOffsetValue(l.dx)+"px",t.style.top=o+this._getSkewOffsetValue(l.dy)+"px"},_getSkewOffsetValue:function(t){var n=e.MatrixUtil.sign(t),r=Math.abs(t);return t=Math.min(r,32767)*n,t},_translateX:0,_translateY:0,_transform:"",translate:function(e,t){this._translateX+=e,this._translateY+=t,this._addTransform("translate",arguments)},translateX:function(e){this._translateX+=e,this._addTransform("translateX",arguments)},translateY:function(e){this._translateY+=e,this._addTransform("translateY",arguments)},skew:function(e,t){this._addTransform("skew",arguments)},skewX:function(e){this._addTransform("skewX",arguments)},skewY:function(e){this._addTransform("skewY",arguments)},rotate:function(e){this._addTransform("rotate",arguments)},scale:function(e,t){this._addTransform("scale",arguments)},on:function(t,n){return e.Node.DOM_EVENTS[t]?e.one("#"+this.get("id")).on(t,n):e.on.apply(this,arguments)},_draw:function(){},_updateHandler:function(e){var t=this,n=t.node;t._fillChangeHandler(),t._strokeChangeHandler(),n.style.width=this.get("width")+"px",n.style.height=this.get("height")+"px",this._draw(),t._updateTransform()},_createGraphicNode:function(e){return e=e||this._type,h.createElement("<"+e+' xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);display:inline-block;" class="vml'+e+'"/>')},_getDefaultFill:function(){return{type:"solid",opacity:1,cx:.5,cy:.5,fx:.5,fy:.5,r:.5}},_getDefaultStroke:function(){return{weight:1,dashstyle:"none",color:"#000",opacity:1}},set:function(){var e=this;p.prototype.set.apply(e,arguments),e.initialized&&e._updateHandler()},getBounds:function(){var t=this instanceof e.VMLPath,n=this.get("width"),r=this.get("height"),i=this.get("x"),s=this.get("y");return t&&(i+=this._left,s+=this._top,n=this._right-this._left,r=this._bottom-this._top),this._getContentRect(n,r,i,s)},_getContentRect:function(t,n,r,i){var s=this.get("transformOrigin"),o=s[0]*t,u=s[1]*n,a=this.matrix.getTransformArray(this.get("transform")),f=new e.Matrix,l,c=a.length,h,p,d,v=this instanceof e.VMLPath;v&&f.translate(this._left,this._top),o=isNaN(o)?0:o,u=isNaN(u)?0:u,f.translate(o,u);for(l=0;l<c;l+=1)h=a[l],p=h.shift(),p&&f[p].apply(f,h);return f.translate(-o,-u),v&&f.translate(-this._left,-this._top),d=f.getContentRect(t,n,r,i),d},toFront:function(){var e=this.get("graphic");e&&e._toFront(this)},toBack:function(){var e=this.get("graphic");e&&e._toBack(this)},_parsePathData:function(t){var n,r,o,u=e.Lang.trim(t.match(i)),a,f,l,c=this._pathSymbolToMethod;if(u){this.clear(),f=u.length||0;for(a=0;a<f;a+=1)l=u[a],r=l.substr(0,1),o=l.substr(1).match(s),n=c[r],n&&(o?this[n].apply(this,o):this[n].apply(this));this.end()}},destroy:function(){var e=this.get("graphic");e?e.removeShape(this):this._destroy()},_destroy:function(){this.node&&(this._fillNode&&(this.node.removeChild(this._fillNode),this._fillNode=null),this._strokeNode&&(this.node.removeChild(this._strokeNode),this._strokeNode=null),e.one(this.node).remove(!0))}},e.VMLDrawing.prototype)),d.ATTRS={transformOrigin:{valueFn:function(){return[.5,.5]}},transform:{setter:function(e){var t,n,r;this.matrix.init(),this._normalizedMatrix.init(),this._transforms=this.matrix.getTransformArray(e),n=this._transforms.length;for(t=0;t<n;++t)r=this._transforms[t];return this._transform=e,e},getter:function(){return this._transform}},x:{value:0},y:{value:0},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this.node;return t&&t.setAttribute("id",e),e}},width:{value:0},height:{value:0},visible:{value:!0,setter:function(e){var t=this.node,n=e?"visible":"hidden";return t&&(t.style.visibility=n),e}},fill:{valueFn:"_getDefaultFill",setter:function(e){var t,n,r=this.get("fill")||this._getDefaultFill();if(e){e.hasOwnProperty("color")&&(e.type="solid");for(t in e)e.hasOwnProperty(t)&&(r[t]=e[t])}return n=r,n&&n.color&&(n.color===undefined||n.color=="none")&&(n.color=null),this._fillFlag=!0,n}},stroke:{valueFn:"_getDefaultStroke",setter:function(e){var t,n,r,i=this.get("stroke")||this._getDefaultStroke();if(e){e.hasOwnProperty("weight")&&(r=parseInt(e.weight,10),isNaN(r)||(e.weight=r));for(t in e)e.hasOwnProperty(t)&&(i[t]=e[t])}return n=i,this._strokeFlag=!0,n}},autoSize:{value:!1},pointerEvents:{value:"visiblePainted"},node:{readOnly:!0,getter:function(){return this.node}},data:{setter:function(e){return this.get("node")&&this._parsePathData(e),e}},graphic:{readOnly:!0,getter:function(){return this._graphic}}},e.VMLShape=d,m=function(){m.superclass.constructor.apply(this,arguments)},m.NAME="path",e.extend(m,e.VMLShape),m.ATTRS=e.merge(e.VMLShape.ATTRS,{width:{getter:function(){var e=Math.max(this._right-this._left,0);return e}},height:{getter:function(){return Math.max(this._bottom-this._top,0)}},path:{readOnly:!0,getter:function(){return this._path}}}),e.VMLPath=m,g=function(){g.superclass.constructor.apply(this,arguments)},g.NAME="rect",e.extend(g,e.VMLShape,{_type:"rect"}),g.ATTRS=e.VMLShape.ATTRS,e.VMLRect=g,y=function(){y.superclass.constructor.apply(this,arguments)},y.NAME="ellipse",e.extend(y,e.VMLShape,{_type:"oval"}),y.ATTRS=e.merge(e.VMLShape.ATTRS,{xRadius:{lazyAdd:!1,getter:function(){var e=this.get("width");return e=Math.round(e/2*100)/100,e},setter:function(e){var t=e*2;return this.set("width",t),e}},yRadius:{lazyAdd:!1,getter:function(){var e=this.get("height");return e=Math.round(e/2*100)/100,e},setter:function(e){var t=e*2;return this.set("height",t),e}}}),e.VMLEllipse=y,v=function(e){v.superclass.constructor.apply(this,arguments)},v.NAME="circle",e.extend(v,d,{_type:"oval"}),v.ATTRS=e.merge(d.ATTRS,{radius:{lazyAdd:!1,value:0},width:{setter:function(e){return this.set("radius",e/2),e},getter:function(){var e=this.get("radius"),t=e&&e>0?e*2:0;return t}},height:{setter:function(e){return this.set("radius",e/2),e},getter:function(){var e=this.get("radius"),t=e&&e>0?e*2:0;return t}}}),e.VMLCircle=v,w=function(){w.superclass.constructor.apply(this,arguments)},w.NAME="vmlPieSlice",e.extend(w,e.VMLShape,e.mix({_type:"shape",_draw:function(e){var t=this.get("cx"),n=this.get("cy"),r=this.get("startAngle"),i=this.get("arc"),s=this.get("radius");this.clear(),this.drawWedge(t,n,r,i,s),this.end()}},e.VMLDrawing.prototype)),w.ATTRS=e.mix({cx:{value:0},cy:{value:0},startAngle:{value:0},arc:{value:0},radius:{value:0}},e.VMLShape.ATTRS),e.VMLPieSlice=w,b=function(){b.superclass.constructor.apply(this,arguments)},b.NAME="vmlGraphic",b.ATTRS={render:{},id:{valueFn:function(){return e.guid()},setter:function(e){var t=this._node;return t&&t.setAttribute("id",e),e}},shapes:{readOnly:!0,getter:function(){return this._shapes}},contentBounds:{readOnly:!0,getter:function(){return this._contentBounds}},node:{readOnly:!0,getter:function(){return this._node}},width:{setter:function(e){return this._node&&(this._node.style.width=e+"px"),e}},height:{setter:function(e){return this._node&&(this._node.style.height=e+"px"),e}},autoSize:{value:!1},preserveAspectRatio:{value:"xMidYMid"},resizeDown:{resizeDown:!1},x:{getter:function(){return this._x},setter:function(e){return this._x=e,this._node&&(this._node.style.left=e+"px"),e}},y:{getter:function(){return this._y},setter:function(e){return this._y=e,this._node&&(this._node.style.top=e+"px"),e}},autoDraw:{value:!0},visible:{value:!0,setter:function(e){return this._toggleVisible(e),e}}},e.extend(b,e.GraphicBase,{set:function(t,n){var r=this,i={autoDraw:!0,autoSize:!0,preserveAspectRatio:!0,resizeDown:!0},s,u=!1;p.prototype.set.apply(r,arguments);if(r._state.autoDraw===!0&&e.Object.size(this._shapes)>0)if(o.isString&&i[t])u=!0;else if(o.isObject(t))for(s in i)if(i.hasOwnProperty(s)&&t[s]){u=!0;break}u&&r._redraw()},_x:0,_y:0,getXY:function(){var t=this.parentNode,n=this.get("x"),r=this.get("y"),i;return t?(i=e.one(t).getXY(),i[0]+=n,i[1]+=r):i=e.DOM._getOffset(this._node),i},initializer:function(e){var t=this.get("render"),n=this.get("visible")?"visible":"hidden";this._shapes={},this._contentBounds={left:0,top:0,right:0,bottom:0},this._node=this._createGraphic(),this._node.style.left=this.get("x")+"px",this._node.style.top=this.get("y")+"px",this._node.style.visibility=n,this._node.setAttribute("id",this.get("id")),t&&this.render(t)},render:function(t){var n=e.one(t),r=this.get("width")||parseInt(n.getComputedStyle("width"),10),i=this.get("height")||parseInt(n.getComputedStyle("height"),10);return n=n||h.body,n.appendChild(this._node),this.parentNode=n,this.set("width",r),this.set("height",i),this},destroy:function(){this.clear(),e.one(this._node).remove(!0)},addShape:function(e){e.graphic=this,this.get("visible")||(e.visible=!1);var t=this._getShapeClass(e.type),n=new t(e);return this._appendShape(n),n._appendStrokeAndFill(),n},_appendShape:function(e){var t=e.node,n=this._frag||this._node;this.get("autoDraw")||this.get("autoSize")=="sizeContentToGraphic"?n.appendChild(t):this._getDocFrag().appendChild(t)},removeShape:function(e){e instanceof d||o.isString(e)&&(e=this._shapes[e]),e&&e instanceof d&&(e._destroy(),this._shapes[e.get("id")]=null,delete this._shapes[e.get("id")]),this.get("autoDraw")&&this._redraw()},removeAllShapes:function(){var e=this._shapes,t;for(t in e)e.hasOwnProperty(t)&&e[t].destroy();this._shapes={}},_removeChildren:function(e){if(e.hasChildNodes()){var t;while(e.firstChild)t=e.firstChild,this._removeChildren(t),e.removeChild(t)}},clear:function(){this.removeAllShapes(),this._removeChildren(this._node)},_toggleVisible:function(e){var t,n=this._shapes,r=e?"visible":"hidden";if(n)for(t in n)n.hasOwnProperty(t)&&n[t].set("visible",e);this._node&&(this._node.style.visibility=r),this._node&&(this._node.style.visibility=r)},setSize:function(e,t){e=Math.round(e),t=Math.round(t),this._node.style.width=e+"px",this._node.style.height=t+"px"},setPosition:function(e,t){e=Math.round(e),t=Math.round(t),this._node.style.left=e+"px",this._node.style.top=t+"px"},_createGraphic:function(){var e=h.createElement('<group xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);padding:0px 0px 0px 0px;display:block;position:absolute;top:0px;left:0px;zoom:1;" />');return e},_createGraphicNode:function(e){return h.createElement("<"+e+' xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);display:inline-block;zoom:1;" />')},getShapeById:function(e){return this._shapes[e]},_getShapeClass:function(e){var t=this._shapeClass[e];return t?t:e},_shapeClass:{circle:e.VMLCircle,rect:e.VMLRect,path:e.VMLPath,ellipse:e.VMLEllipse,pieslice:e.VMLPieSlice},batch:function(e){var t=this.get("autoDraw");this.set("autoDraw",!1),e.apply(),this.set("autoDraw",t)},_getDocFrag:function(){return this._frag||(this._frag=h.createDocumentFragment()),this._frag},addToRedrawQueue:function(e){var t,n;this._shapes[e.get("id")]=e,this.get("resizeDown")||(t=e.getBounds(),n=this._contentBounds,n.left=n.left<t.left?n.left:t.left,n.top=n.top<t.top?n.top:t.top,n.right=n.right>t.right?n.right:t.right,n.bottom=n.bottom>t.bottom?n.bottom:t.bottom,n.width=n.right-n.left,n.height=n.bottom-n.top,this._contentBounds=n),this.get("autoDraw")&&this._redraw()},_redraw:function(){var e=this.get("autoSize"),t,n=this.parentNode,r=parseFloat(n.getComputedStyle("width")),i=parseFloat(n.getComputedStyle("height")),s=0,o=0,u=this.get("resizeDown")?this._getUpdatedContentBounds():this._contentBounds,a=u.left,f=u.right,l=u.top,c=u.bottom,h=f-a,p=c-l,d,v,m,g,y,b=this.get("visible");this._node.style.visibility="hidden",e?(e=="sizeContentToGraphic"?(t=this.get("preserveAspectRatio"),t=="none"||h/p===r/i?(s=a,o=l,v=h,m=p):h*i/p>r?(d=i/r,v=h,m=h*d,y=r*(p/h)*(m/i),o=this._calculateCoordOrigin(t.slice(5).toLowerCase(),y,m),o=l+o,s=a):(d=r/i,v=p*d,m=p,g=i*(h/p)*(v/r),s=this._calculateCoordOrigin(t.slice(1,4).toLowerCase(),g,v),s+=a,o=l),this._node.style.width=r+"px",this._node.style.height=i+"px",this._node.coordOrigin=s+", "+o):(v=h,m=p,this._node.style.width=h+"px",this._node.style.height=p+"px",this._state.width=h,this._state.height=p),this._node.coordSize=v+", "+m):(this._node.style.width=r+"px",this._node.style.height=i+"px",this._node.coordSize=r+", "+i),this._frag&&(this._node.appendChild(this._frag),this._frag=null),b&&(this._node.style.visibility="visible")},_calculateCoordOrigin:function(e,t,n){var r;switch(e){case"min":r=0;break;case"mid":r=(t-n)/2;break;case"max":r=t-n}return r},_getUpdatedContentBounds:function(){var e,t,n,r=this._shapes,i={};for(t in r)r.hasOwnProperty(t)&&(n=r[t],e=n.getBounds(),i.left=o.isNumber(i.left)?Math.min(i.left,e.left):e.left,i.top=o.isNumber(i.top)?Math.min(i.top,e.top):e.top,i.right=o.isNumber(i.right)?Math.max(i.right,e.right):e.right,i.bottom=o.isNumber(i.bottom)?Math.max(i.bottom,e.bottom):e.bottom);return i.left=o.isNumber(i.left)?i.left:0,i.top=o.isNumber(i.top)?i.top:0,i.right=o.isNumber(i.right)?i.right:0,i.bottom=o.isNumber(i.bottom)?i.bottom:0,this._contentBounds=i,i},_toFront:function(t){var n=this._node;t instanceof e.VMLShape&&(t=t.get("node")),n&&t&&n.appendChild(t)},_toBack:function(t){var n=this._node,r;t instanceof e.VMLShape&&(t=t.get("node")),n&&t&&(r=n.firstChild,r?n.insertBefore(t,r):n.appendChild(t))}}),e.VMLGraphic=b},"3.7.3",{requires:["graphics"]});
diff --git a/js/yui3/graphics/graphics-min.js b/js/yui3/graphics/graphics-min.js
new file mode 100644
index 000000000..e7ddf6843
--- /dev/null
+++ b/js/yui3/graphics/graphics-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("graphics",function(e,t){var n="setter",r=e.Plugin.Host,i="value",s="valueFn",o="readOnly",u=e.Lang,a="string",f="writeOnce",l,c;c=function(){var t=this;t._ATTR_E_FACADE={},e.EventTarget.call(this,{emitFacade:!0}),t._state={},t.prototype=e.mix(c.prototype,t.prototype)},c.prototype={addAttrs:function(e){var t=this,r=this.constructor.ATTRS,a,l,c,h=t._state;for(l in r)r.hasOwnProperty(l)&&(a=r[l],a.hasOwnProperty(i)?h[l]=a.value:a.hasOwnProperty(s)&&(c=a.valueFn,u.isString(c)?h[l]=t[c].apply(t):h[l]=c.apply(t)));t._state=h;for(l in r)if(r.hasOwnProperty(l)){a=r[l];if(a.hasOwnProperty(o)&&a.readOnly)continue;a.hasOwnProperty(f)&&a.writeOnce&&(a.readOnly=!0),e&&e.hasOwnProperty(l)&&(a.hasOwnProperty(n)?t._state[l]=a.setter.apply(t,[e[l]]):t._state[l]=e[l])}},get:function(e){var t=this,n,r=t.constructor.ATTRS;if(r&&r[e])return n=r[e].getter,n?typeof n==a?t[n].apply(t):r[e].getter.apply(t):t._state[e];return null},set:function(e,t){var n;if(u.isObject(e))for(n in e)e.hasOwnProperty(n)&&this._set(n,e[n]);else this._set.apply(this,arguments)},_set:function(e,t){var n=this,r,i,s=n.constructor.ATTRS;s&&s.hasOwnProperty(e)&&(r=s[e].setter,r&&(i=[t],typeof r==a?t=n[r].apply(n,i):t=s[e].setter.apply(n,i)),n._state[e]=t)}},e.mix(c,e.EventTarget,!1,null,1),e.AttributeLite=c,l=function(t){var n=this,r=e.Plugin&&e.Plugin.Host;n._initPlugins&&r&&r.call(n),n.name=n.constructor.NAME,n._eventPrefix=n.constructor.EVENT_PREFIX||n.constructor.NAME,c.call(n),n.addAttrs(t),n.init.apply(this,arguments),n._initPlugins&&n._initPlugins(t),n.initialized=!0},l.NAME="baseGraphic",l.prototype={init:function(){this.publish("init",{fireOnce:!0}),this.initializer.apply(this,arguments),this.fire("init",{cfg:arguments[0]})},_camelCaseConcat:function(e,t){return e+t.charAt(0).toUpperCase()+t.slice(1)}},e.mix(l,e.AttributeLite,!1,null,1),e.mix(l,r,!1,null,1),l.prototype.constructor=l,l.plug=r.plug,l.unplug=r.unplug,e.GraphicBase=l},"3.7.3",{requires:["node","event-custom","pluginhost","matrix","classnamemanager"]});
diff --git a/js/yui3/handlebars-base/handlebars-base-min.js b/js/yui3/handlebars-base/handlebars-base-min.js
new file mode 100644
index 000000000..e55055cad
--- /dev/null
+++ b/js/yui3/handlebars-base/handlebars-base-min.js
@@ -0,0 +1,12 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("handlebars-base",function(e,t){
+/*!
+Handlebars.js - Copyright (C) 2011 Yehuda Katz
+https://raw.github.com/wycats/handlebars.js/master/LICENSE
+*/
+;var n={};n.VERSION="1.0.beta.5",n.helpers={},n.partials={},n.registerHelper=function(e,t,n){n&&(t.not=n),this.helpers[e]=t},n.registerPartial=function(e,t){this.partials[e]=t},n.registerHelper("helperMissing",function(e){if(arguments.length===2)return undefined;throw new Error("Could not find property '"+e+"'")});var r=Object.prototype.toString,i="[object Function]";n.registerHelper("blockHelperMissing",function(e,t){var n=t.inverse||function(){},s=t.fn,o="",u=r.call(e);u===i&&(e=e.call(this));if(e===!0)return s(this);if(e===!1||e==null)return n(this);if(u==="[object Array]"){if(e.length>0)for(var a=0,f=e.length;a<f;a++)o+=s(e[a]);else o=n(this);return o}return s(e)}),n.registerHelper("each",function(e,t){var n=t.fn,r=t.inverse,i="";if(e&&e.length>0)for(var s=0,o=e.length;s<o;s++)i+=n(e[s]);else i=r(this);return i}),n.registerHelper("if",function(e,t){var s=r.call(e);return s===i&&(e=e.call(this)),!e||n.Utils.isEmpty(e)?t.inverse(this):t.fn(this)}),n.registerHelper("unless",function(e,t){var r=t.fn,i=t.inverse;return t.fn=i,t.inverse=r,n.helpers["if"].call(this,e,t)}),n.registerHelper("with",function(e,t){return t.fn(e)}),n.registerHelper("log",function(e){n.log(e)});var s=e.Lang;n.Exception=function(e){var t=Error.prototype.constructor.apply(this,arguments),n;for(n in t)t.hasOwnProperty(n)&&(this[n]=t[n]);this.message=t.message},n.Exception.prototype=new Error,n.SafeString=function(e){this.string=e},n.SafeString.prototype.toString=function(){return this.string.toString()},n.Utils={escapeExpression:function(t){return t===""?t:t instanceof n.SafeString?t.toString():t===!1||!s.isValue(t)?"":e.Escape.html(t)},isEmpty:function(e){return e===!1||!s.isValue(e)||s.isArray(e)&&!e.length?!0:!1}},n.VM={template:function(e){var t={escapeExpression:n.Utils.escapeExpression,invokePartial:n.VM.invokePartial,programs:[],program:function(e,t,r){var i=this.programs[e];return r?n.VM.program(t,r):i?i:(i=this.programs[e]=n.VM.program(t),i)},programWithDepth:n.VM.programWithDepth,noop:n.VM.noop};return function(r,i){return i=i||{},e.call(t,n,r,i.helpers,i.partials,i.data)}},programWithDepth:function(e,t,n){var r=Array.prototype.slice.call(arguments,2);return function(n,i){return i=i||{},e.apply(this,[n,i.data||t].concat(r))}},program:function(e,t){return function(n,r){return r=r||{},e(n,r.data||t)}},noop:function(){return""},invokePartial:function(e,t,r,i,s,o){var u={helpers:i,partials:s,data:o};if(e===undefined)throw new n.Exception("The partial "+t+" could not be found");if(e instanceof Function)return e(r,u);if(!n.compile)throw new n.Exception("The partial "+t+" could not be compiled when running in runtime-only mode");return s[t]=n.compile(e),s[t](r,u)}},n.template=n.VM.template,e.Handlebars=n,n.VERSION+="-yui"},"3.7.3",{requires:["escape"]});
diff --git a/js/yui3/handlebars-compiler/handlebars-compiler-min.js b/js/yui3/handlebars-compiler/handlebars-compiler-min.js
new file mode 100644
index 000000000..7e0a801f5
--- /dev/null
+++ b/js/yui3/handlebars-compiler/handlebars-compiler-min.js
@@ -0,0 +1,12 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("handlebars-compiler",function(e,t){
+/*!
+Handlebars.js - Copyright (C) 2011 Yehuda Katz
+https://raw.github.com/wycats/handlebars.js/master/LICENSE
+*/
+;var n=e.Handlebars,r=function(){function n(){this.yy={}}var e={trace:function(){},yy:{},symbols_:{error:2,root:3,program:4,EOF:5,statements:6,simpleInverse:7,statement:8,openInverse:9,closeBlock:10,openBlock:11,mustache:12,partial:13,CONTENT:14,COMMENT:15,OPEN_BLOCK:16,inMustache:17,CLOSE:18,OPEN_INVERSE:19,OPEN_ENDBLOCK:20,path:21,OPEN:22,OPEN_UNESCAPED:23,OPEN_PARTIAL:24,params:25,hash:26,param:27,STRING:28,INTEGER:29,BOOLEAN:30,hashSegments:31,hashSegment:32,ID:33,EQUALS:34,pathSegments:35,SEP:36,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"},productions_:[0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],performAction:function(t,n,r,i,s,o,u){var a=o.length-1;switch(s){case 1:return o[a-1];case 2:this.$=new i.ProgramNode(o[a-2],o[a]);break;case 3:this.$=new i.ProgramNode(o[a]);break;case 4:this.$=new i.ProgramNode([]);break;case 5:this.$=[o[a]];break;case 6:o[a-1].push(o[a]),this.$=o[a-1];break;case 7:this.$=new i.BlockNode(o[a-2],o[a-1].inverse,o[a-1],o[a]);break;case 8:this.$=new i.BlockNode(o[a-2],o[a-1],o[a-1].inverse,o[a]);break;case 9:this.$=o[a];break;case 10:this.$=o[a];break;case 11:this.$=new i.ContentNode(o[a]);break;case 12:this.$=new i.CommentNode(o[a]);break;case 13:this.$=new i.MustacheNode(o[a-1][0],o[a-1][1]);break;case 14:this.$=new i.MustacheNode(o[a-1][0],o[a-1][1]);break;case 15:this.$=o[a-1];break;case 16:this.$=new i.MustacheNode(o[a-1][0],o[a-1][1]);break;case 17:this.$=new i.MustacheNode(o[a-1][0],o[a-1][1],!0);break;case 18:this.$=new i.PartialNode(o[a-1]);break;case 19:this.$=new i.PartialNode(o[a-2],o[a-1]);break;case 20:break;case 21:this.$=[[o[a-2]].concat(o[a-1]),o[a]];break;case 22:this.$=[[o[a-1]].concat(o[a]),null];break;case 23:this.$=[[o[a-1]],o[a]];break;case 24:this.$=[[o[a]],null];break;case 25:o[a-1].push(o[a]),this.$=o[a-1];break;case 26:this.$=[o[a]];break;case 27:this.$=o[a];break;case 28:this.$=new i.StringNode(o[a]);break;case 29:this.$=new i.IntegerNode(o[a]);break;case 30:this.$=new i.BooleanNode(o[a]);break;case 31:this.$=new i.HashNode(o[a]);break;case 32:o[a-1].push(o[a]),this.$=o[a-1];break;case 33:this.$=[o[a]];break;case 34:this.$=[o[a-2],o[a]];break;case 35:this.$=[o[a-2],new i.StringNode(o[a])];break;case 36:this.$=[o[a-2],new i.IntegerNode(o[a])];break;case 37:this.$=[o[a-2],new i.BooleanNode(o[a])];break;case 38:this.$=new i.IdNode(o[a]);break;case 39:o[a-2].push(o[a]),this.$=o[a-2];break;case 40:this.$=[o[a]]}},table:[{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],defaultActions:{16:[2,1],37:[2,23],53:[2,21]},parseError:function(t,n){throw new Error(t)},parse:function(t){function d(e){r.length=r.length-2*e,i.length=i.length-e,s.length=s.length-e}function v(){var e;return e=n.lexer.lex()||1,typeof e!="number"&&(e=n.symbols_[e]||e),e}var n=this,r=[0],i=[null],s=[],o=this.table,u="",a=0,f=0,l=0,c=2,h=1;this.lexer.setInput(t),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,this.yy.parser=this,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var p=this.lexer.yylloc;s.push(p),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var m,g,y,b,w,E,S={},x,T,N,C;for(;;){y=r[r.length-1];if(this.defaultActions[y])b=this.defaultActions[y];else{if(m===null||typeof m=="undefined")m=v();b=o[y]&&o[y][m]}if(typeof b=="undefined"||!b.length||!b[0]){var k="";if(!l){C=[];for(x in o[y])this.terminals_[x]&&x>2&&C.push("'"+this.terminals_[x]+"'");this.lexer.showPosition?k="Parse error on line "+(a+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+C.join(", ")+", got '"+(this.terminals_[m]||m)+"'":k="Parse error on line "+(a+1)+": Unexpected "+(m==1?"end of input":"'"+(this.terminals_[m]||m)+"'"),this.parseError(k,{text:this.lexer.match,token:this.terminals_[m]||m,line:this.lexer.yylineno,loc:p,expected:C})}if(l==3){if(m==h)throw new Error(k||"Parsing halted.");f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,m=v()}for(;;){if(c.toString()in o[y])break;if(y===0)throw new Error(k||"Parsing halted.");d(1),y=r[r.length-1]}g=m==2?null:m,m=c,y=r[r.length-1],b=o[y]&&o[y][c],l=3}if(b[0]instanceof Array&&b.length>1)throw new Error("Parse Error: multiple actions possible at state: "+y+", token: "+m);switch(b[0]){case 1:r.push(m),i.push(this.lexer.yytext),s.push(this.lexer.yylloc),r.push(b[1]),m=null,g?(m=g,g=null):(f=this.lexer.yyleng,u=this.lexer.yytext,a=this.lexer.yylineno,p=this.lexer.yylloc,l>0&&l--);break;case 2:T=this.productions_[b[1]][1],S.$=i[i.length-T],S._$={first_line:s[s.length-(T||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(T||1)].first_column,last_column:s[s.length-1].last_column},E=this.performAction.call(S,u,f,a,this.yy,b[1],i,s);if(typeof E!="undefined")return E;T&&(r=r.slice(0,-1*T*2),i=i.slice(0,-1*T),s=s.slice(0,-1*T)),r.push(this.productions_[b[1]][0]),i.push(S.$),s.push(S._$),N=o[r[r.length-2]][r[r.length-1]],r.push(N);break;case 3:return!0}}return!0}},t=function(){var e={EOF:1,parseError:function(t,n){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,n)},setInput:function(e){return this._input=e,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var e=this._input[0];this.yytext+=e,this.yyleng++,this.match+=e,this.matched+=e;var t=e.match(/\n/);return t&&this.yylineno++,this._input=this._input.slice(1),e},unput:function(e){return this._input=e+this._input,this},more:function(){return this._more=!0,this},less:function(e){this._input=this.match.slice(e)+this._input},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=(new Array(e.length+1)).join("-");return e+this.upcomingInput()+"\n"+t+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var e,t,n,r,i,s;this._more||(this.yytext="",this.match="");var o=this._currentRules();for(var u=0;u<o.length;u++){n=this._input.match(this.rules[o[u]]);if(n&&(!t||n[0].length>t[0].length)){t=n,r=u;if(!this.options.flex)break}}if(t){s=t[0].match(/\n.*/g),s&&(this.yylineno+=s.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:s?s[s.length-1].length-1:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],e=this.performAction.call(this,this.yy,this,o[r],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1);if(e)return e;return}return this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var t=this.next();return typeof t!="undefined"?t:this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(t){this.begin(t)}};return e.options={},e.performAction=function(t,n,r,i){var s=i;switch(r){case 0:n.yytext.slice(-1)!=="\\"&&this.begin("mu"),n.yytext.slice(-1)==="\\"&&(n.yytext=n.yytext.substr(0,n.yyleng-1),this.begin("emu"));if(n.yytext)return 14;break;case 1:return 14;case 2:return this.popState(),14;case 3:return 24;case 4:return 16;case 5:return 20;case 6:return 19;case 7:return 19;case 8:return 23;case 9:return 23;case 10:return n.yytext=n.yytext.substr(3,n.yyleng-5),this.popState(),15;case 11:return 22;case 12:return 34;case 13:return 33;case 14:return 33;case 15:return 36;case 16:break;case 17:return this.popState(),18;case 18:return this.popState(),18;case 19:return n.yytext=n.yytext.substr(1,n.yyleng-2).replace(/\\"/g,'"'),28;case 20:return 30;case 21:return 30;case 22:return 29;case 23:return 33;case 24:return n.yytext=n.yytext.substr(1,n.yyleng-2),33;case 25:return"INVALID";case 26:return 5}},e.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{)))/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/],e.conditions={mu:{rules:[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],inclusive:!1},emu:{rules:[2],inclusive:!1},INITIAL:{rules:[0,1,26],inclusive:!0}},e}();return e.lexer=t,n.prototype=e,e.Parser=n,new n}();typeof require!="undefined"&&typeof exports!="undefined"&&(exports.parser=r,exports.Parser=r.Parser,exports.parse=function(){return r.parse.apply(r,arguments)},exports.main=function(t){if(!t[1])throw new Error("Usage: "+t[0]+" FILE");var n,r;return typeof process!="undefined"?n=require("fs").readFileSync(require("path").resolve(t[1]),"utf8"):n=require("file").path(require("file").cwd()).join(t[1]).read({charset:"utf-8"}),exports.parser.parse(n)},typeof module!="undefined"&&require.main===module&&exports.main(typeof process!="undefined"?process.argv.slice(1):require("system").args)),n.Parser=r,n.parse=function(e){return n.Parser.yy=n.AST,n.Parser.parse(e)},n.print=function(e){return(new n.PrintVisitor).accept(e)},n.logger={DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,log:function(e,t){}},n.log=function(e,t){n.logger.log(e,t)},function(){n.AST={},n.AST.ProgramNode=function(e,t){this.type="program",this.statements=e,t&&(this.inverse=new n.AST.ProgramNode(t))},n.AST.MustacheNode=function(e,t,n){this.type="mustache",this.escaped=!n,this.hash=t;var r=this.id=e[0],i=this.params=e.slice(1),s=this.eligibleHelper=r.isSimple;this.isHelper=s&&(i.length||t)},n.AST.PartialNode=function(e,t){this.type="partial",this.id=e,this.context=t};var e=function(e,t){if(e.original!==t.original)throw new n.Exception(e.original+" doesn't match "+t.original)};n.AST.BlockNode=function(t,n,r,i){e(t.id,i),this.type="block",this.mustache=t,this.program=n,this.inverse=r,this.inverse&&!this.program&&(this.isInverse=!0)},n.AST.ContentNode=function(e){this.type="content",this.string=e},n.AST.HashNode=function(e){this.type="hash",this.pairs=e},n.AST.IdNode=function(e){this.type="ID",this.original=e.join(".");var t=[],n=0;for(var r=0,i=e.length;r<i;r++){var s=e[r];s===".."?n++:s==="."||s==="this"?this.isScoped=!0:t.push(s)}this.parts=t,this.string=t.join("."),this.depth=n,this.isSimple=e.length===1&&!this.isScoped&&n===0},n.AST.StringNode=function(e){this.type="STRING",this.string=e},n.AST.IntegerNode=function(e){this.type="INTEGER",this.integer=e},n.AST.BooleanNode=function(e){this.type="BOOLEAN",this.bool=e},n.AST.CommentNode=function(e){this.type="comment",this.comment=e}}(),n.Compiler=function(){},n.JavaScriptCompiler=function(){},function(e,t){e.prototype={compiler:e,disassemble:function(){var e=this.opcodes,t,n=[],r,i;for(var s=0,o=e.length;s<o;s++){t=e[s];if(t.opcode==="DECLARE")n.push("DECLARE "+t.name+"="+t.value);else{r=[];for(var u=0;u<t.args.length;u++)i=t.args[u],typeof i=="string"&&(i='"'+i.replace("\n","\\n")+'"'),r.push(i);n.push(t.opcode+" "+r.join(" "))}}return n.join("\n")},guid:0,compile:function(e,t){this.children=[],this.depths={list:[]},this.options=t;var n=this.options.knownHelpers;this.options.knownHelpers={helperMissing:!0,blockHelperMissing:!0,each:!0,"if":!0,unless:!0,"with":!0,log:!0};if(n)for(var r in n)this.options.knownHelpers[r]=n[r];return this.program(e)},accept:function(e){return this[e.type](e)},program:function(e){var t=e.statements,n;this.opcodes=[];for(var r=0,i=t.length;r<i;r++)n=t[r],this[n.type](n);return this.isSimple=i===1,this.depths.list=this.depths.list.sort(function(e,t){return e-t}),this},compileProgram:function(e){var t=(new this.compiler).compile(e,this.options),n=this.guid++,r;this.usePartial=this.usePartial||t.usePartial,this.children[n]=t;for(var i=0,s=t.depths.list.length;i<s;i++){r=t.depths.list[i];if(r<2)continue;this.addDepth(r-1)}return n},block:function(e){var t=e.mustache,n=e.program,r=e.inverse;n&&(n=this.compileProgram(n)),r&&(r=this.compileProgram(r));var i=this.classifyMustache(t);i==="helper"?this.helperMustache(t,n,r):i==="simple"?(this.simpleMustache(t),this.opcode("pushProgram",n),this.opcode("pushProgram",r),this.opcode("pushLiteral","{}"),this.opcode("blockValue")):(this.ambiguousMustache(t,n,r),this.opcode("pushProgram",n),this.opcode("pushProgram",r),this.opcode("pushLiteral","{}"),this.opcode("ambiguousBlockValue")),this.opcode("append")},hash:function(e){var t=e.pairs,n,r;this.opcode("push","{}");for(var i=0,s=t.length;i<s;i++)n=t[i],r=n[1],this.accept(r),this.opcode("assignToHash",n[0])},partial:function(e){var t=e.id;this.usePartial=!0,e.context?this.ID(e.context):this.opcode("push","depth0"),this.opcode("invokePartial",t.original),this.opcode("append")},content:function(e){this.opcode("appendContent",e.string)},mustache:function(e){var t=this.options,n=this.classifyMustache(e);n==="simple"?this.simpleMustache(e):n==="helper"?this.helperMustache(e):this.ambiguousMustache(e),e.escaped&&!t.noEscape?this.opcode("appendEscaped"):this.opcode("append")},ambiguousMustache:function(e,t,n){var r=e.id,i=r.parts[0];this.opcode("getContext",r.depth),this.opcode("pushProgram",t),this.opcode("pushProgram",n),this.opcode("invokeAmbiguous",i)},simpleMustache:function(e,t,n){var r=e.id;this.addDepth(r.depth),this.opcode("getContext",r.depth);if(r.parts.length){this.opcode("lookupOnContext",r.parts[0]);for(var i=1,s=r.parts.length;i<s;i++)this.opcode("lookup",r.parts[i])}else this.opcode("pushContext");this.opcode("resolvePossibleLambda")},helperMustache:function(e,t,n){var r=this.setupFullMustacheParams(e,t,n),i=e.id.parts[0];if(this.options.knownHelpers[i])this.opcode("invokeKnownHelper",r.length,i);else{if(this.knownHelpersOnly)throw new Error("You specified knownHelpersOnly, but used the unknown helper "+i);this.opcode("invokeHelper",r.length,i)}},ID:function(e){this.addDepth(e.depth),this.opcode("getContext",e.depth),this.opcode("lookupOnContext",e.parts[0]);for(var t=1,n=e.parts.length;t<n;t++)this.opcode("lookup",e.parts[t])},STRING:function(e){this.opcode("pushString",e.string)},INTEGER:function(e){this.opcode("pushLiteral",e.integer)},BOOLEAN:function(e){this.opcode("pushLiteral",e.bool)},comment:function(){},opcode:function(e){this.opcodes.push({opcode:e,args:[].slice.call(arguments,1)})},declare:function(e,t){this.opcodes.push({opcode:"DECLARE",name:e,value:t})},addDepth:function(e){if(e===0)return;this.depths[e]||(this.depths[e]=!0,this.depths.list.push(e))},classifyMustache:function(e){var t=e.isHelper,n=e.eligibleHelper,r=this.options;if(n&&!t){var i=e.id.parts[0];r.knownHelpers[i]?t=!0:r.knownHelpersOnly&&(n=!1)}return t?"helper":n?"ambiguous":"simple"},pushParams:function(e){var t=e.length,n;while(t--)n=e[t],this.options.stringParams?(n.depth&&this.addDepth(n.depth),this.opcode("getContext",n.depth||0),this.opcode("pushStringParam",n.string)):this[n.type](n)},setupMustacheParams:function(e){var t=e.params;return this.pushParams(t),e.hash?this.hash(e.hash):this.opcode("pushLiteral","{}"),t},setupFullMustacheParams:function(e,t,n){var r=e.params;return this.pushParams(r),this.opcode("pushProgram",t),this.opcode("pushProgram",n),e.hash?this.hash(e.hash):this.opcode("pushLiteral","{}"),r}};var r=function(e){this.value=e};t.prototype={nameLookup:function(e,n,r){return/^[0-9]+$/.test(n)?e+"["+n+"]":t.isValidJavaScriptVariableName(n)?e+"."+n:e+"['"+n+"']"},appendToBuffer:function(e){return this.environment.isSimple?"return "+e+";":"buffer += "+e+";"},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",compile:function(e,t,r,i){this.environment=e,this.options=t||{},n.log(n.logger.DEBUG,this.environment.disassemble()+"\n\n"),this.name=this.environment.name,this.isChild=!!r,this.context=r||{programs:[],aliases:{}},this.preamble(),this.stackSlot=0,this.stackVars=[],this.registers={list:[]},this.compileStack=[],this.compileChildren(e,t);var s=e.opcodes,o;this.i=0;for(u=s.length;this.i<u;this.i++)o=s[this.i],o.opcode==="DECLARE"?this[o.name]=o.value:this[o.opcode].apply(this,o.args);return this.createFunctionContext(i)},nextOpcode:function(){var e=this.environment.opcodes,t=e[this.i+1];return e[this.i+1]},eat:function(e){this.i=this.i+1},preamble:function(){var e=[];if(!this.isChild){var t=this.namespace,n="helpers = helpers || "+t+".helpers;";this.environment.usePartial&&(n=n+" partials = partials || "+t+".partials;"),e.push(n)}else e.push("");this.environment.isSimple?e.push(""):e.push(", buffer = "+this.initializeBuffer()),this.lastContext=0,this.source=e},createFunctionContext:function(e){var t=this.stackVars.concat(this.registers.list);t.length>0&&(this.source[1]=this.source[1]+", "+t.join(", "));if(!this.isChild){var r=[];for(var i in this.context.aliases)this.source[1]=this.source[1]+", "+i+"="+this.context.aliases[i]}this.source[1]&&(this.source[1]="var "+this.source[1].substring(2)+";"),this.isChild||(this.source[1]+="\n"+this.context.programs.join("\n")+"\n"),this.environment.isSimple||this.source.push("return buffer;");var s=this.isChild?["depth0","data"]:["Handlebars","depth0","helpers","partials","data"];for(var o=0,u=this.environment.depths.list.length;o<u;o++)s.push("depth"+this.environment.depths.list[o]);if(e)return s.push(this.source.join("\n ")),Function.apply(this,s);var a="function "+(this.name||"")+"("+s.join(",")+") {\n "+this.source.join("\n ")+"}";return n.log(n.logger.DEBUG,a+"\n\n"),a},blockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var e=["depth0"];this.setupParams(0,e),this.replaceStack(function(t){return e.splice(1,0,t),t+" = blockHelperMissing.call("+e.join(", ")+")"})},ambiguousBlockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var e=["depth0"];this.setupParams(0,e);var t=this.topStack();e.splice(1,0,t),this.source.push("if (!"+this.lastHelper+") { "+t+" = blockHelperMissing.call("+e.join(", ")+"); }")},appendContent:function(e){this.source.push(this.appendToBuffer(this.quotedString(e)))},append:function(){var e=this.popStack();this.source.push("if("+e+" || "+e+" === 0) { "+this.appendToBuffer(e)+" }"),this.environment.isSimple&&this.source.push("else { "+this.appendToBuffer("''")+" }")},appendEscaped:function(){var e=this.nextOpcode(),t="";this.context.aliases.escapeExpression="this.escapeExpression",e&&e.opcode==="appendContent"&&(t=" + "+this.quotedString(e.args[0]),this.eat(e)),this.source.push(this.appendToBuffer("escapeExpression("+this.popStack()+")"+t))},getContext:function(e){this.lastContext!==e&&(this.lastContext=e)},lookupOnContext:function(e){this.pushStack(this.nameLookup("depth"+this.lastContext,e,"context"))},pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.context.aliases.functionType='"function"',this.replaceStack(function(e){return"typeof "+e+" === functionType ? "+e+"() : "+e})},lookup:function(e){this.replaceStack(function(t){return t+" == null || "+t+" === false ? "+t+" : "+this.nameLookup(t,e,"context")})},pushStringParam:function(e){this.pushStackLiteral("depth"+this.lastContext),this.pushString(e)},pushString:function(e){this.pushStackLiteral(this.quotedString(e))},push:function(e){this.pushStack(e)},pushLiteral:function(e){this.pushStackLiteral(e)},pushProgram:function(e){e!=null?this.pushStackLiteral(this.programExpression(e)):this.pushStackLiteral(null)},invokeHelper:function(e,t){this.context.aliases.helperMissing="helpers.helperMissing";var n=this.lastHelper=this.setupHelper(e,t);this.register("foundHelper",n.name),this.pushStack("foundHelper ? foundHelper.call("+n.callParams+") "+": helperMissing.call("+n.helperMissingParams+")")},invokeKnownHelper:function(e,t){var n=this.setupHelper(e,t);this.pushStack(n.name+".call("+n.callParams+")")},invokeAmbiguous:function(e){this.context.aliases.functionType='"function"',this.pushStackLiteral("{}");var t=this.setupHelper(0,e),n=this.lastHelper=this.nameLookup("helpers",e,"helper");this.register("foundHelper",n);var r=this.nameLookup("depth"+this.lastContext,e,"context"),i=this.nextStack();this.source.push("if (foundHelper) { "+i+" = foundHelper.call("+t.callParams+"); }"),this.source.push("else { "+i+" = "+r+"; "+i+" = typeof "+i+" === functionType ? "+i+"() : "+i+"; }")},invokePartial:function(e){var t=[this.nameLookup("partials",e,"partial"),"'"+e+"'",this.popStack(),"helpers","partials"];this.options.data&&t.push("data"),this.context.aliases.self="this",this.pushStack("self.invokePartial("+t.join(", ")+");")},assignToHash:function(e){var t=this.popStack(),n=this.topStack();this.source.push(n+"['"+e+"'] = "+t+";")},compiler:t,compileChildren:function(e,t){var n=e.children,r,i;for(var s=0,o=n.length;s<o;s++){r=n[s],i=new this.compiler,this.context.programs.push("");var u=this.context.programs.length;r.index=u,r.name="program"+u,this.context.programs[u]=i.compile(r,t,this.context)}},programExpression:function(e){this.context.aliases.self="this";if(e==null)return"self.noop";var t=this.environment.children[e],n=t.depths.list,r,i=[t.index,t.name,"data"];for(var s=0,o=n.length;s<o;s++)r=n[s],r===1?i.push("depth0"):i.push("depth"+(r-1));return n.length===0?"self.program("+i.join(", ")+")":(i.shift(),"self.programWithDepth("+i.join(", ")+")")},register:function(e,t){this.useRegister(e),this.source.push(e+" = "+t+";")},useRegister:function(e){this.registers[e]||(this.registers[e]=!0,this.registers.list.push(e))},pushStackLiteral:function(e){return this.compileStack.push(new r(e)),e},pushStack:function(e){return this.source.push(this.incrStack()+" = "+e+";"),this.compileStack.push("stack"+this.stackSlot),"stack"+this.stackSlot},replaceStack:function(e){var t=e.call(this,this.topStack());return this.source.push(this.topStack()+" = "+t+";"),"stack"+this.stackSlot},nextStack:function(e){var t=this.incrStack();return this.compileStack.push("stack"+this.stackSlot),t},incrStack:function(){return this.stackSlot++,this.stackSlot>this.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),"stack"+this.stackSlot},popStack:function(){var e=this.compileStack.pop();return e instanceof r?e.value:(this.stackSlot--,e)},topStack:function(){var e=this.compileStack[this.compileStack.length-1];return e instanceof r?e.value:e},quotedString:function(e){return'"'+e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")+'"'},setupHelper:function(e,t){var n=[];this.setupParams(e,n);var r=this.nameLookup("helpers",t,"helper");return{params:n,name:r,callParams:["depth0"].concat(n).join(", "),helperMissingParams:["depth0",this.quotedString(t)].concat(n).join(", ")}},setupParams:function(e,t){var n=[],r=[],i,s,o;n.push("hash:"+this.popStack()),s=this.popStack(),o=this.popStack();if(o||s)o||(this.context.aliases.self="this",o="self.noop"),s||(this.context.aliases.self="this",s="self.noop"),n.push("inverse:"+s),n.push("fn:"+o);for(var u=0;u<e;u++)i=this.popStack(),t.push(i),this.options.stringParams&&r.push(this.popStack());return this.options.stringParams&&n.push("contexts:["+r.join(",")+"]"),this.options.data&&n.push("data:data"),t.push("{"+n.join(",")+"}"),t.join(", ")}};var i="break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public let yield".split(" "),s=t.RESERVED_WORDS={};for(var o=0,u=i.length;o<u;o++)s[i[o]]=!0;t.isValidJavaScriptVariableName=function(e){return!t.RESERVED_WORDS[e]&&/^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(e)?!0:!1}}(n.Compiler,n.JavaScriptCompiler),n.precompile=function(e,t){t=t||{};var r=n.parse(e),i=(new n.Compiler).compile(r,t);return(new n.JavaScriptCompiler).compile(i,t)},n.compile=function(e,t){function i(){var r=n.parse(e),i=(new n.Compiler).compile(r,t),s=(new n.JavaScriptCompiler).compile(i,t,undefined,!0);return n.template(s)}t=t||{};var r;return function(e,t){return r||(r=i()),r.call(this,e,t)}};var i=["debug","info","warn","error"];n.logger.log=function(e,t){},n.render=function(e,t,r){return n.compile(e)(t,r)}},"3.7.3",{requires:["handlebars-base"]});
diff --git a/js/yui3/highlight-accentfold/highlight-accentfold-min.js b/js/yui3/highlight-accentfold/highlight-accentfold-min.js
new file mode 100644
index 000000000..806b17259
--- /dev/null
+++ b/js/yui3/highlight-accentfold/highlight-accentfold-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("highlight-accentfold",function(e,t){var n=e.Text.AccentFold,r=e.Escape,i={},s=e.mix(e.Highlight,{allFold:function(t,o,u){var a=s._TEMPLATE,f=[],l=0,c,h,p,d,v;u=e.merge({escapeHTML:!1,replacer:function(e,n,r,i){var s;if(n&&!/\s/.test(r))return e;s=r.length,f.push([t.substring(l,i),t.substr(i,s)]),l=i+s}},u||i),s.all(n.fold(t),n.fold(o),u),l<t.length&&f.push([t.substr(l)]);for(h=0,p=f.length;h<p;++h){c=r.html(f[h][0]);if(d=f[h][1])c+=a.replace(/\{s\}/g,r.html(d));f[h]=c}return f.join("")},startFold:function(e,t){return s.allFold(e,t,{startsWith:!0})},wordsFold:function(e,t){var i=s._TEMPLATE;return s.words(e,n.fold(t),{mapper:function(e,t){return t.hasOwnProperty(n.fold(e))?i.replace(/\{s\}/g,r.html(e)):r.html(e)}})}})},"3.7.3",{requires:["highlight-base","text-accentfold"]});
diff --git a/js/yui3/highlight-base/highlight-base-min.js b/js/yui3/highlight-base/highlight-base-min.js
new file mode 100644
index 000000000..60e1fba86
--- /dev/null
+++ b/js/yui3/highlight-base/highlight-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("highlight-base",function(e,t){var n=e.Array,r=e.Escape,i=e.Text.WordBreak,s=e.Lang.isArray,o={},u="(&[^;\\s]*)?",a={_REGEX:u+"(%needles)",_REPLACER:function(e,t,n){return t&&!/\s/.test(n)?e:a._TEMPLATE.replace(/\{s\}/g,n)},_START_REGEX:"^"+u+"(%needles)",_TEMPLATE:'<b class="'+e.ClassNameManager.getClassName("highlight")+'">{s}</b>',all:function(e,t,n){var i=[],u,f,l,c,h,p;n||(n=o),u=n.escapeHTML!==!1,h=n.startsWith?a._START_REGEX:a._REGEX,p=n.replacer||a._REPLACER,t=s(t)?t:[t];for(f=0,l=t.length;f<l;++f)c=t[f],c&&i.push(r.regex(u?r.html(c):c));return u&&(e=r.html(e)),i.length?e.replace(new RegExp(h.replace("%needles",i.join("|")),n.caseSensitive?"g":"gi"),p):e},allCase:function(t,n,r){return a.all(t,n,e.merge(r||o,{caseSensitive:!0}))},start:function(t,n,r){return a.all(t,n,e.merge(r||o,{startsWith:!0}))},startCase:function(e,t){return a.start(e,t,{caseSensitive:!0})},words:function(e,t,u){var f,l,c=a._TEMPLATE,h;return u||(u=o),f=!!u.caseSensitive,t=n.hash(s(t)?t:i.getUniqueWords(t,{ignoreCase:!f})),l=u.mapper||function(e,t){return t.hasOwnProperty(f?e:e.toLowerCase())?c.replace(/\{s\}/g,r.html(e)):r.html(e)},h=i.getWords(e,{includePunctuation:!0,includeWhitespace:!0}),n.map(h,function(e){return l(e,t)}).join("")},wordsCase:function(e,t){return a.words(e,t,{caseSensitive:!0})}};e.Highlight=a},"3.7.3",{requires:["array-extras","classnamemanager","escape","text-wordbreak"]});
diff --git a/js/yui3/history-base/history-base-min.js b/js/yui3/history-base/history-base-min.js
new file mode 100644
index 000000000..45f27e084
--- /dev/null
+++ b/js/yui3/history-base/history-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("history-base",function(e,t){function p(){this._init.apply(this,arguments)}function d(e){return n.type(e)==="object"}var n=e.Lang,r=e.Object,i=YUI.namespace("Env.History"),s=e.Array,o=e.config.doc,u=o.documentMode,a=e.config.win,f={merge:!0},l="change",c="add",h="replace";e.augment(p,e.EventTarget,null,null,{emitFacade:!0,prefix:"history",preventable:!1,queueable:!0}),i._state||(i._state={}),p.NAME="historyBase",p.SRC_ADD=c,p.SRC_REPLACE=h,p.html5=!!(a.history&&a.history.pushState&&a.history.replaceState&&("onpopstate"in a||e.UA.gecko>=2)&&(!e.UA.android||e.UA.android>=2.4)),p.nativeHashChange=("onhashchange"in a||"onhashchange"in o)&&(!u||u>7),e.mix(p.prototype,{_init:function(e){var t;e=this._config=e||{},this.force=!!e.force,t=this._initialState=this._initialState||e.initialState||null,this.publish(l,{broadcast:2,defaultFn:this._defChangeFn}),t&&this.replace(t)},add:function(){var e=s(arguments,0,!0);return e.unshift(c),this._change.apply(this,e)},addValue:function(e,t,n){var r={};return r[e]=t,this._change(c,r,n)},get:function(t){var n=i._state,s=d(n);return t?s&&r.owns(n,t)?n[t]:undefined:s?e.mix({},n,!0):n},replace:function(){var e=s(arguments,0,!0);return e.unshift(h),this._change.apply(this,e)},replaceValue:function(e,t,n){var r={};return r[e]=t,this._change(h,r,n)},_change:function(t,n,r){return r=r?e.merge(f,r):f,r.merge&&d(n)&&d(i._state)&&(n=e.merge(i._state,n)),this._resolveChanges(t,n,r),this},_fireEvents:function(e,t,n){this.fire(l,{_options:n,changed:t.changed,newVal:t.newState,prevVal:t.prevState,removed:t.removed,src:e}),r.each(t.changed,function(t,n){this._fireChangeEvent(e,n,t)},this),r.each(t.removed,function(t,n){this._fireRemoveEvent(e,n,t)},this)},_fireChangeEvent:function(e,t,n){this.fire(t+"Change",{newVal:n.newVal,prevVal:n.prevVal,src:e})},_fireRemoveEvent:function(e,t,n){this.fire(t+"Remove",{prevVal:n,src:e})},_resolveChanges:function(e,t,n){var s={},o,u=i._state,a={};t||(t={}),n||(n={}),d(t)&&d(u)?(r.each(t,function(e,t){var n=u[t];e!==n&&(s[t]={newVal:e,prevVal:n},o=!0)},this),r.each(u,function(e,n){if(!r.owns(t,n)||t[n]===null)delete t[n],a[n]=e,o=!0},this)):o=t!==u,(o||this.force)&&this._fireEvents(e,{changed:s,newState:t,prevState:u,removed:a},n)},_storeState:function(e,t){i._state=t||{}},_defChangeFn:function(e){this._storeState(e.src,e.newVal,e._options)}},!0),e.HistoryBase=p},"3.7.3",{requires:["event-custom-complex"]});
diff --git a/js/yui3/history-hash-ie/history-hash-ie-min.js b/js/yui3/history-hash-ie/history-hash-ie-min.js
new file mode 100644
index 000000000..cdfd7efaf
--- /dev/null
+++ b/js/yui3/history-hash-ie/history-hash-ie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("history-hash-ie",function(e,t){if(e.UA.ie&&!e.HistoryBase.nativeHashChange){var n=e.Do,r=YUI.namespace("Env.HistoryHash"),i=e.HistoryHash,s=r._iframe,o=e.config.win;i.getIframeHash=function(){if(!s||!s.contentWindow)return"";var e=i.hashPrefix,t=s.contentWindow.location.hash.substr(1);return e&&t.indexOf(e)===0?t.replace(e,""):t},i._updateIframe=function(e,t){var n=s&&s.contentWindow&&s.contentWindow.document,r=n&&n.location;if(!n||!r)return;t?r.replace(e.charAt(0)==="#"?e:"#"+e):(n.open().close(),r.hash=e)},n.before(i._updateIframe,i,"replaceHash",i,!0),s||e.on("domready",function(){var t=i.getHash();s=r._iframe=e.Node.getDOMNode(e.Node.create('<iframe src="javascript:0" style="display:none" height="0" width="0" tabindex="-1" title="empty"/>')),e.config.doc.documentElement.appendChild(s),i._updateIframe(t||"#"),e.on("hashchange",function(e){t=e.newHash,i.getIframeHash()!==t&&i._updateIframe(t)},o),e.later(50,null,function(){var e=i.getIframeHash();e!==t&&i.setHash(e)},null,!0)})}},"3.7.3",{requires:["history-hash","node-base"]});
diff --git a/js/yui3/history-hash/history-hash-min.js b/js/yui3/history-hash/history-hash-min.js
new file mode 100644
index 000000000..04ecd2bfd
--- /dev/null
+++ b/js/yui3/history-hash/history-hash-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("history-hash",function(e,t){function p(){p.superclass.constructor.apply(this,arguments)}var n=e.HistoryBase,r=e.Lang,i=e.Array,s=e.Object,o=YUI.namespace("Env.HistoryHash"),u="hash",a,f,l,c=e.config.win,h=e.config.useHistoryHTML5;e.extend(p,n,{_init:function(t){var n=p.parseHash();t=t||{},this._initialState=t.initialState?e.merge(t.initialState,n):n,e.after("hashchange",e.bind(this._afterHashChange,this),c),p.superclass._init.apply(this,arguments)},_change:function(e,t,n){return s.each(t,function(e,n){r.isValue(e)&&(t[n]=e.toString())}),p.superclass._change.call(this,e,t,n)},_storeState:function(e,t){var r=p.decode,i=p.createHash(t);p.superclass._storeState.apply(this,arguments),e!==u&&r(p.getHash())!==r(i)&&p[e===n.SRC_REPLACE?"replaceHash":"setHash"](i)},_afterHashChange:function(e){this._resolveChanges(u,p.parseHash(e.newHash),{})}},{NAME:"historyHash",SRC_HASH:u,hashPrefix:"",_REGEX_HASH:/([^\?#&]+)=([^&]+)/g,createHash:function(e){var t=p.encode,n=[];return s.each(e,function(e,i){r.isValue(e)&&n.push(t(i)+"="+t(e))}),n.join("&")},decode:function(e){return decodeURIComponent(e.replace(/\+/g," "))},encode:function(e){return encodeURIComponent(e).replace(/%20/g,"+")},getHash:e.UA.gecko?function(){var t=e.getLocation(),n=/#(.*)$/.exec(t.href),r=n&&n[1]||"",i=p.hashPrefix;return i&&r.indexOf(i)===0?r.replace(i,""):r}:function(){var t=e.getLocation(),n=t.hash.substring(1),r=p.hashPrefix;return r&&n.indexOf(r)===0?n.replace(r,""):n},getUrl:function(){return location.href},parseHash:function(e){var t=p.decode,n,i,s,o,u={},a=p.hashPrefix,f;e=r.isValue(e)?e:p.getHash();if(a){f=e.indexOf(a);if(f===0||f===1&&e.charAt(0)==="#")e=e.replace(a,"")}s=e.match(p._REGEX_HASH)||[];for(n=0,i=s.length;n<i;++n)o=s[n].split("="),u[t(o[0])]=t(o[1]);return u},replaceHash:function(t){var n=e.getLocation(),r=n.href.replace(/#.*$/,"");t.charAt(0)==="#"&&(t=t.substring(1)),n.replace(r+"#"+(p.hashPrefix||"")+t)},setHash:function(t){var n=e.getLocation();t.charAt(0)==="#"&&(t=t.substring(1)),n.hash=(p.hashPrefix||"")+t}}),a=o._notifiers,a||(a=o._notifiers=[]),e.Event.define("hashchange",{on:function(t,n,r){(t.compareTo(c)||t.compareTo(e.config.doc.body))&&a.push(r)},detach:function(e,t,n){var r=i.indexOf(a,n);r!==-1&&a.splice(r,1)}}),f=p.getHash(),l=p.getUrl(),n.nativeHashChange?o._hashHandle||(o._hashHandle=e.Event.attach("hashchange",function(e){var t=p.getHash(),n=p.getUrl();i.each(a.concat(),function(r){r.fire({_event:e,oldHash:f,oldUrl:l,newHash:t,newUrl:n})}),f=t,l=n},c)):o._hashPoll||(o._hashPoll=e.later(50,null,function(){var e=p.getHash(),t,n;f!==e&&(n=p.getUrl(),t={oldHash:f,oldUrl:l,newHash:e,newUrl:n},f=e,l=n,i.each(a.concat(),function(e){e.fire(t)}))},null,!0)),e.HistoryHash=p;if(h===!1||!e.History&&h!==!0&&(!n.html5||!e.HistoryHTML5))e.History=p},"3.7.3",{requires:["event-synthetic","history-base","yui-later"]});
diff --git a/js/yui3/history-html5/history-html5-min.js b/js/yui3/history-html5/history-html5-min.js
new file mode 100644
index 000000000..0f60dc5ae
--- /dev/null
+++ b/js/yui3/history-html5/history-html5-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("history-html5",function(e,t){function a(){a.superclass.constructor.apply(this,arguments)}var n=e.HistoryBase,r=e.Lang,i=e.config.win,s=e.config.useHistoryHTML5,o="popstate",u=n.SRC_REPLACE;e.extend(a,n,{_init:function(t){var n=i.history.state;e.Object.isEmpty(n)&&(n=null),t||(t={}),t.initialState&&r.type(t.initialState)==="object"&&r.type(n)==="object"?this._initialState=e.merge(t.initialState,n):this._initialState=n,e.on("popstate",this._onPopState,i,this),a.superclass._init.apply(this,arguments)},_storeState:function(t,n,r){t!==o&&i.history[t===u?"replaceState":"pushState"](n,r.title||e.config.doc.title||"",r.url||null),a.superclass._storeState.apply(this,arguments)},_onPopState:function(e){this._resolveChanges(o,e._event.state||null)}},{NAME:"historyhtml5",SRC_POPSTATE:o}),e.Node.DOM_EVENTS.popstate||(e.Node.DOM_EVENTS.popstate=1),e.HistoryHTML5=a;if(s===!0||s!==!1&&n.html5)e.History=a},"3.7.3",{optional:["json"],requires:["event-base","history-base","node-base"]});
diff --git a/js/yui3/imageloader/imageloader-min.js b/js/yui3/imageloader/imageloader-min.js
new file mode 100644
index 000000000..f847b95e1
--- /dev/null
+++ b/js/yui3/imageloader/imageloader-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("imageloader",function(e,t){e.ImgLoadGroup=function(){this._init(),e.ImgLoadGroup.superclass.constructor.apply(this,arguments)},e.ImgLoadGroup.NAME="imgLoadGroup",e.ImgLoadGroup.ATTRS={name:{value:""},timeLimit:{value:null},foldDistance:{validator:e.Lang.isNumber,setter:function(e){return this._setFoldTriggers(),e},lazyAdd:!1},className:{value:null,setter:function(e){return this._className=e,e},lazyAdd:!1},classNameAction:{value:"default"}};var n={_init:function(){this._triggers=[],this._imgObjs={},this._timeout=null,this._classImageEls=null,this._className=null,this._areFoldTriggersSet=!1,this._maxKnownHLimit=0,e.on("domready",this._onloadTasks,this)},addTrigger:function(t,n){if(!t||!n)return this;var r=function(){this.fetch()};return this._triggers.push(e.on(n,r,t,this)),this},addCustomTrigger:function(t,n){if(!t)return this;var r=function(){this.fetch()};return e.Lang.isUndefined(n)?this._triggers.push(e.on(t,r,this)):this._triggers.push(n.on(t,r,this)),this},_setFoldTriggers:function(){if(this._areFoldTriggersSet)return;var t=function(){this._foldCheck()};this._triggers.push(e.on("scroll",t,window,this)),this._triggers.push(e.on("resize",t,window,this)),this._areFoldTriggersSet=!0},_onloadTasks:function(){var t=this.get("timeLimit");t&&t>0&&(this._timeout=setTimeout(this._getFetchTimeout(),t*1e3)),e.Lang.isUndefined(this.get("foldDistance"))||this._foldCheck()},_getFetchTimeout:function(){var e=this;return function(){e.fetch()}},registerImage:function(){var t=arguments[0].domId;return t?(this._imgObjs[t]=new e.ImgLoadImgObj(arguments[0]),this._imgObjs[t]):null},fetch:function(){this._clearTriggers(),this._fetchByClass();for(var e in this._imgObjs)this._imgObjs.hasOwnProperty(e)&&this._imgObjs[e].fetch()},_clearTriggers:function(){clearTimeout(this._timeout);for(var e=0,t=this._triggers.length;e<t;e++)this._triggers[e].detach()},_foldCheck:function(){var t=!0,n=e.DOM.viewportRegion(),r=n.bottom+this.get("foldDistance"),i,s,o,u,a;if(r<=this._maxKnownHLimit)return;this._maxKnownHLimit=r;for(i in this._imgObjs)this._imgObjs.hasOwnProperty(i)&&(s=this._imgObjs[i].fetch(r),t=t&&s);if(this._className){this._classImageEls===null&&(this._classImageEls=[],o=e.all("."+this._className),o.each(function(e){this._classImageEls.push({el:e,y:e.getY(),fetched:!1})},this)),o=this._classImageEls;for(u=0,a=o.length;u<a;u++){if(o[u].fetched)continue;o[u].y&&o[u].y<=r?(this._updateNodeClassName(o[u].el),o[u].fetched=!0):t=!1}}t&&this._clearTriggers()},_updateNodeClassName:function(e){var t;this.get("classNameAction")=="enhanced"&&e.get("tagName").toLowerCase()=="img"&&(t=e.getStyle("backgroundImage"),/url\(["']?(.*?)["']?\)/.test(t),t=RegExp.$1,e.set("src",t),e.setStyle("backgroundImage","")),e.removeClass(this._className)},_fetchByClass:function(){if(!this._className)return;e.all("."+this._className).each(e.bind(this._updateNodeClassName,this))}};e.extend(e.ImgLoadGroup,e.Base,n),e.ImgLoadImgObj=function(){e.ImgLoadImgObj.superclass.constructor.apply(this,arguments),this._init()},e.ImgLoadImgObj.NAME="imgLoadImgObj",e.ImgLoadImgObj.ATTRS={domId:{value:null,writeOnce:!0},bgUrl:{value:null},srcUrl:{value:null},width:{value:null},height:{value:null},setVisible:{value:!1},isPng:{value:!1},sizingMethod:{value:"scale"},enabled:{value:"true"}};var r={_init:function(){this._fetched=!1,this._imgEl=null,this._yPos=null},fetch:function(t){if(this._fetched)return!0;var n=this._getImgEl(),r;if(!n)return!1;if(t){r=this._getYPos();if(!r||r>t)return!1}return this.get("bgUrl")!==null?this.get("isPng")&&e.UA.ie&&e.UA.ie<=6?n.setStyle("filter",'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+this.get("bgUrl")+'", sizingMethod="'+this.get("sizingMethod")+'", enabled="'+this.get("enabled")+'")'):n.setStyle("backgroundImage","url('"+this.get("bgUrl")+"')"):this.get("srcUrl")!==null&&n.setAttribute("src",this.get("srcUrl")),this.get("setVisible")&&n.setStyle("visibility","visible"),this.get("width")&&n.setAttribute("width",this.get("width")),this.get("height")&&n.setAttribute("height",this.get("height")),this._fetched=!0,!0},_getImgEl:function(){return this._imgEl===null&&(this._imgEl=e.one("#"+this.get("domId"))),this._imgEl},_getYPos:function(){return this._yPos===null&&(this._yPos=this._getImgEl().getY()),this._yPos}};e.extend(e.ImgLoadImgObj,e.Base,r)},"3.7.3",{requires:["base-base","node-style","node-screen"]});
diff --git a/js/yui3/intl-base/intl-base-min.js b/js/yui3/intl-base/intl-base-min.js
new file mode 100644
index 000000000..a8bbae53c
--- /dev/null
+++ b/js/yui3/intl-base/intl-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("intl-base",function(e,t){var n=/[, ]/;e.mix(e.namespace("Intl"),{lookupBestLang:function(t,r){function a(e){var t;for(t=0;t<r.length;t+=1)if(e.toLowerCase()===r[t].toLowerCase())return r[t]}var i,s,o,u;e.Lang.isString(t)&&(t=t.split(n));for(i=0;i<t.length;i+=1){s=t[i];if(!s||s==="*")continue;while(s.length>0){o=a(s);if(o)return o;u=s.lastIndexOf("-");if(!(u>=0))break;s=s.substring(0,u),u>=2&&s.charAt(u-2)==="-"&&(s=s.substring(0,u-2))}}return""}})},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/intl/intl-min.js b/js/yui3/intl/intl-min.js
new file mode 100644
index 000000000..1709b7e7c
--- /dev/null
+++ b/js/yui3/intl/intl-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("intl",function(e,t){var n={},r="yuiRootLang",i="yuiActiveLang",s=[];e.mix(e.namespace("Intl"),{_mod:function(e){return n[e]||(n[e]={}),n[e]},setLang:function(e,t){var n=this._mod(e),s=n[i],o=!!n[t];return o&&t!==s&&(n[i]=t,this.fire("intl:langChange",{module:e,prevVal:s,newVal:t===r?"":t})),o},getLang:function(e){var t=this._mod(e)[i];return t===r?"":t},add:function(e,t,n){t=t||r,this._mod(e)[t]=n,this.setLang(e,t)},get:function(t,n,r){var s=this._mod(t),o;return r=r||s[i],o=s[r]||{},n?o[n]:e.merge(o)},getAvailableLangs:function(t){var n=e.Env._loader,r=n&&n.moduleInfo[t],i=r&&r.lang;return i?i.concat():s}}),e.augment(e.Intl,e.EventTarget),e.Intl.publish("intl:langChange",{emitFacade:!0})},"3.7.3",{requires:["intl-base","event-custom"]});
diff --git a/js/yui3/io-base/io-base-min.js b/js/yui3/io-base/io-base-min.js
new file mode 100644
index 000000000..c4952f348
--- /dev/null
+++ b/js/yui3/io-base/io-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-base",function(e,t){function o(t){var n=this;n._uid="io:"+s++,n._init(t),e.io._map[n._uid]=n}var n=["start","complete","end","success","failure","progress"],r=["status","statusText","responseText","responseXML"],i=e.config.win,s=0;o.prototype={_id:0,_headers:{"X-Requested-With":"XMLHttpRequest"},_timeout:{},_init:function(t){var r=this,i,s;r.cfg=t||{},e.augment(r,e.EventTarget);for(i=0,s=n.length;i<s;++i)r.publish("io:"+n[i],e.merge({broadcast:1},t)),r.publish("io-trn:"+n[i],t)},_create:function(t,n){var r=this,s={id:e.Lang.isNumber(n)?n:r._id++,uid:r._uid},o=t.xdr?t.xdr.use:null,u=t.form&&t.form.upload?"iframe":null,a;return o==="native"&&(o=e.UA.ie&&!l?"xdr":null,r.setHeader("X-Requested-With")),a=o||u,s=a?e.merge(e.IO.customTransport(a),s):e.merge(e.IO.defaultTransport(),s),s.notify&&(t.notify=function(e,t,n){r.notify(e,t,n)}),a||i&&i.FormData&&t.data instanceof i.FormData&&(s.c.upload.onprogress=function(e){r.progress(s,e,t)},s.c.onload=function(e){r.load(s,e,t)},s.c.onerror=function(e){r.error(s,e,t)},s.upload=!0),s},_destroy:function(t){i&&!t.notify&&!t.xdr&&(u&&!t.upload?t.c.onreadystatechange=null:t.upload?(t.c.upload.onprogress=null,t.c.onload=null,t.c.onerror=null):e.UA.ie&&!t.e&&t.c.abort()),t=t.c=null},_evt:function(t,r,i){var s=this,o,u=i.arguments,a=s.cfg.emitFacade,f="io:"+t,l="io-trn:"+t;this.detach(l),r.e&&(r.c={status:0,statusText:r.e}),o=[a?{id:r.id,data:r.c,cfg:i,arguments:u}:r.id],a||(t===n[0]||t===n[2]?u&&o.push(u):(r.evt?o.push(r.evt):o.push(r.c),u&&o.push(u))),o.unshift(f),s.fire.apply(s,o),i.on&&(o[0]=l,s.once(l,i.on[t],i.context||e),s.fire.apply(s,o))},start:function(e,t){this._evt(n[0],e,t)},complete:function(e,t){this._evt(n[1],e,t)},end:function(e,t){this._evt(n[2],e,t),this._destroy(e)},success:function(e,t){this._evt(n[3],e,t),this.end(e,t)},failure:function(e,t){this._evt(n[4],e,t),this.end(e,t)},progress:function(e,t,r){e.evt=t,this._evt(n[5],e,r)},load:function(e,t,r){e.evt=t.target,this._evt(n[1],e,r)},error:function(e,t,r){e.evt=t,this._evt(n[4],e,r)},_retry:function(e,t,n){return this._destroy(e),n.xdr.use="flash",this.send(t,n,e.id)},_concat:function(e,t){return e+=(e.indexOf("?")===-1?"?":"&")+t,e},setHeader:function(e,t){t?this._headers[e]=t:delete this._headers[e]},_setHeaders:function(t,n){n=e.merge(this._headers,n),e.Object.each(n,function(e,r){e!=="disable"&&t.setRequestHeader(r,n[r])})},_startTimeout:function(e,t){var n=this;n._timeout[e.id]=setTimeout(function(){n._abort(e,"timeout")},t)},_clearTimeout:function(e){clearTimeout(this._timeout[e]),delete this._timeout[e]},_result:function(e,t){var n;try{n=e.c.status}catch(r){n=0}n>=200&&n<300||n===304||n===1223?this.success(e,t):this.failure(e,t)},_rS:function(e,t){var n=this;e.c.readyState===4&&(t.timeout&&n._clearTimeout(e.id),setTimeout(function(){n.complete(e,t),n._result(e,t)},0))},_abort:function(e,t){e&&e.c&&(e.e=t,e.c.abort())},send:function(t,n,i){var s,o,u,a,f,c,h=this,p=t,d={};n=n?e.Object(n):{},s=h._create(n,i),o=n.method?n.method.toUpperCase():"GET",f=n.sync,c=n.data,e.Lang.isObject(c)&&!c.nodeType&&!s.upload&&(c=e.QueryString.stringify(c));if(n.form){if(n.form.upload)return h.upload(s,t,n);c=h._serialize(n.form,c)}if(c)switch(o){case"GET":case"HEAD":case"DELETE":p=h._concat(p,c),c="";break;case"POST":case"PUT":n.headers=e.merge({"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},n.headers)}if(s.xdr)return h.xdr(p,s,n);if(s.notify)return s.c.send(s,t,n);!f&&!s.upload&&(s.c.onreadystatechange=function(){h._rS(s,n)});try{s.c.open(o,p,!f,n.username||null,n.password||null),h._setHeaders(s.c,n.headers||{}),h.start(s,n),n.xdr&&n.xdr.credentials&&l&&(s.c.withCredentials=!0),s.c.send(c);if(f){for(u=0,a=r.length;u<a;++u)d[r[u]]=s.c[r[u]];return d.getAllResponseHeaders=function(){return s.c.getAllResponseHeaders()},d.getResponseHeader=function(e){return s.c.getResponseHeader(e)},h.complete(s,n),h._result(s,n),d}}catch(v){if(s.xdr)return h._retry(s,t,n);h.complete(s,n),h._result(s,n)}return n.timeout&&h._startTimeout(s,n.timeout),{id:s.id,abort:function(){return s.c?h._abort(s,"abort"):!1},isInProgress:function(){return s.c?s.c.readyState%4:!1},io:h}}},e.io=function(t,n){var r=e.io._map["io:0"]||new o;return r.send.apply(r,[t,n])},e.io.header=function(t,n){var r=e.io._map["io:0"]||new o;r.setHeader(t,n)},e.IO=o,e.io._map={};var u=i&&i.XMLHttpRequest,a=i&&i.XDomainRequest,f=i&&i.ActiveXObject,l=u&&"withCredentials"in new XMLHttpRequest;e.mix(e.IO,{_default:"xhr",defaultTransport:function(t){if(!t){var n={c:e.IO.transports[e.IO._default](),notify:e.IO._default==="xhr"?!1:!0};return n}e.IO._default=t},transports:{xhr:function(){return u?new XMLHttpRequest:f?new ActiveXObject("Microsoft.XMLHTTP"):null},xdr:function(){return a?new XDomainRequest:null},iframe:function(){return{}},flash:null,nodejs:null},customTransport:function(t){var n={c:e.IO.transports[t]()};return n[t==="xdr"||t==="flash"?"xdr":"notify"]=!0,n}}),e.mix(e.IO.prototype,{notify:function(e,t,n){var r=this;switch(e){case"timeout":case"abort":case"transport error":t.c={status:0,statusText:e},e="failure";default:r[e].apply(r,[t,n])}}})},"3.7.3",{requires:["event-custom-base","querystring-stringify-simple"]});
diff --git a/js/yui3/io-form/io-form-min.js b/js/yui3/io-form/io-form-min.js
new file mode 100644
index 000000000..ae2b4d504
--- /dev/null
+++ b/js/yui3/io-form/io-form-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-form",function(e,t){var n=encodeURIComponent;e.mix(e.IO.prototype,{_serialize:function(t,r){var i=[],s=t.useDisabled||!1,o=0,u=typeof t.id=="string"?t.id:t.id.getAttribute("id"),a,f,l,c,h,p,d,v,m,g;u||(u=e.guid("io:"),t.id.setAttribute("id",u)),f=e.config.doc.getElementById(u);for(p=0,d=f.elements.length;p<d;++p){a=f.elements[p],h=a.disabled,l=a.name;if(s?l:l&&!h){l=n(l)+"=",c=n(a.value);switch(a.type){case"select-one":a.selectedIndex>-1&&(g=a.options[a.selectedIndex],i[o++]=l+n(g.attributes.value&&g.attributes.value.specified?g.value:g.text));break;case"select-multiple":if(a.selectedIndex>-1)for(v=a.selectedIndex,m=a.options.length;v<m;++v)g=a.options[v],g.selected&&(i[o++]=l+n(g.attributes.value&&g.attributes.value.specified?g.value:g.text));break;case"radio":case"checkbox":a.checked&&(i[o++]=l+c);break;case"file":case undefined:case"reset":case"button":break;case"submit":default:i[o++]=l+c}}}return r?i.join("&")+"&"+r:i.join("&")}},!0)},"3.7.3",{requires:["io-base","node-base"]});
diff --git a/js/yui3/io-nodejs/io-nodejs-min.js b/js/yui3/io-nodejs/io-nodejs-min.js
new file mode 100644
index 000000000..3cc3044d2
--- /dev/null
+++ b/js/yui3/io-nodejs/io-nodejs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-nodejs",function(e,t){e.IO.request||(e.IO.request=require("request").defaults({jar:!1}));var n=require("http").STATUS_CODES,r=function(e){var t=[];return Object.keys(e).forEach(function(n){t.push(n+": "+e[n])}),t.join("\n")};e.IO.transports.nodejs=function(){return{send:function(t,i,s){s.notify("start",t,s),s.method=s.method||"GET",s.method=s.method.toUpperCase();var o={method:s.method,uri:i};s.data&&(e.Lang.isObject(s.data)?e.QueryString&&e.QueryString.stringify&&(o.body=e.QueryString.stringify(s.data)):e.Lang.isString(s.data)&&(o.body=s.data),o.method==="GET"&&(o.uri+=(o.uri.indexOf("?")>-1?"&":"?")+o.body,o.body="")),s.headers&&(o.headers=s.headers),s.timeout&&(o.timeout=s.timeout),s.request&&e.mix(o,s.request),e.IO.request(o,function(e,i){if(e){t.c=e,s.notify(e.code==="ETIMEDOUT"?"timeout":"failure",t,s);return}i&&(t.c={status:i.statusCode,statusCode:i.statusCode,statusText:n[i.statusCode],headers:i.headers,responseText:i.body,responseXML:null,getResponseHeader:function(e){return this.headers[e]},getAllResponseHeaders:function(){return r(this.headers)}}),s.notify("complete",t,s),s.notify(i&&i.statusCode>=200&&i.statusCode<=299?"success":"failure",t,s)});var u={io:t};return u}}},e.IO.defaultTransport("nodejs")},"3.7.3",{requires:["io-base"]});
diff --git a/js/yui3/io-queue/io-queue-min.js b/js/yui3/io-queue/io-queue-min.js
new file mode 100644
index 000000000..568a234a9
--- /dev/null
+++ b/js/yui3/io-queue/io-queue-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-queue",function(e,t){function r(e,t){return n.queue.apply(n,[e,t])}var n=e.io._map["io:0"]||new e.IO;e.mix(e.IO.prototype,{_q:new e.Queue,_qActiveId:null,_qInit:!1,_qState:1,_qShift:function(){var e=this,t=e._q.next();e._qActiveId=t.id,e._qState=0,e.send(t.uri,t.cfg,t.id)},queue:function(t,n){var r=this,i={uri:t,cfg:n,id:this._id++};return r._qInit||(e.on("io:complete",function(e,t){r._qNext(e)},r),r._qInit=!0),r._q.add(i),r._qState===1&&r._qShift(),i},_qNext:function(e){var t=this;t._qState=1,t._qActiveId===e&&t._q.size()>0&&t._qShift()},qPromote:function(e){this._q.promote(e)},qRemove:function(e){this._q.remove(e)},qEmpty:function(){this._q=new e.Queue},qStart:function(){var e=this;e._qState=1,e._q.size()>0&&e._qShift()},qStop:function(){this._qState=0},qSize:function(){return this._q.size()}},!0),r.start=function(){n.qStart()},r.stop=function(){n.qStop()},r.promote=function(e){n.qPromote(e)},r.remove=function(e){n.qRemove(e)},r.size=function(){n.qSize()},r.empty=function(){n.qEmpty()},e.io.queue=r},"3.7.3",{requires:["io-base","queue-promote"]});
diff --git a/js/yui3/io-upload-iframe/io-upload-iframe-min.js b/js/yui3/io-upload-iframe/io-upload-iframe-min.js
new file mode 100644
index 000000000..9a628ab65
--- /dev/null
+++ b/js/yui3/io-upload-iframe/io-upload-iframe-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-upload-iframe",function(e,t){function u(t,n,r){var i=e.Node.create('<iframe src="#" id="io_iframe'+t.id+'" name="io_iframe'+t.id+'" />');i._node.style.position="absolute",i._node.style.top="-1000px",i._node.style.left="-1000px",e.one("body").appendChild(i),e.on("load",function(){r._uploadComplete(t,n)},"#io_iframe"+t.id)}function a(t){e.Event.purgeElement("#io_iframe"+t,!1),e.one("body").removeChild(e.one("#io_iframe"+t))}var n=e.config.win,r=e.config.doc,i=r.documentMode&&r.documentMode>=8,s=decodeURIComponent,o=e.IO.prototype.end;e.mix(e.IO.prototype,{_addData:function(t,n){e.Lang.isObject(n)&&(n=e.QueryString.stringify(n));var i=[],o=n.split("="),u,a;for(u=0,a=o.length-1;u<a;u++)i[u]=r.createElement("input"),i[u].type="hidden",i[u].name=s(o[u].substring(o[u].lastIndexOf("&")+1)),i[u].value=u+1===a?s(o[u+1]):s(o[u+1].substring(0,o[u+1].lastIndexOf("&"))),t.appendChild(i[u]);return i},_removeData:function(e,t){var n,r;for(n=0,r=t.length;n<r;n++)e.removeChild(t[n])},_setAttrs:function(t,n,r){t.setAttribute("action",r),t.setAttribute("method","POST"),t.setAttribute("target","io_iframe"+n),t.setAttribute(e.UA.ie&&!i?"encoding":"enctype","multipart/form-data")},_resetAttrs:function(t,n){e.Object.each(n,function(e,n){e?t.setAttribute(n,e):t.removeAttribute(n)})},_startUploadTimeout:function(e,t){var r=this;r._timeout[e.id]=n.setTimeout(function(){e.status=0,e.statusText="timeout",r.complete(e,t),r.end(e,t)},t.timeout)},_clearUploadTimeout:function(e){var t=this;n.clearTimeout(t._timeout[e]),delete t._timeout[e]},_uploadComplete:function(t,r){var i=this,s=e.one("#io_iframe"+t.id).get("contentWindow.document"),o=s.one("body"),u;r.timeout&&i._clearUploadTimeout(t.id);try{o?(u=o.one("pre:first-child"),t.c.responseText=u?u.get("text"):o.get("text")):t.c.responseXML=s._node}catch(f){t.e="upload failure"}i.complete(t,r),i.end(t,r),n.setTimeout(function(){a(t.id)},0)},_upload:function(t,n,i){var s=this,o=typeof i.form.id=="string"?r.getElementById(i.form.id):i.form.id,u={action:o.getAttribute("action"),target:o.getAttribute("target")},f;return s._setAttrs(o,t.id,n),i.data&&(f=s._addData(o,i.data)),i.timeout&&s._startUploadTimeout(t,i),o.submit(),s.start(t,i),i.data&&s._removeData(o,f),{id:t.id,abort:function(){t.status=0,t.statusText="abort";if(!e.one("#io_iframe"+t.id))return!1;a(t.id),s.complete(t,i),s.end(t,i,u)},isInProgress:function(){return e.one("#io_iframe"+t.id)?!0:!1},io:s}},upload:function(e,t,n){return u(e,n,this),this._upload(e,t,n)},end:function(e,t,n){if(t&&t.form&&t.form.upload){var r=this;r._resetAttrs(f,n)}return o.call(this,e,t)}})},"3.7.3",{requires:["io-base","node-base"]});
diff --git a/js/yui3/io-xdr/io-xdr-min.js b/js/yui3/io-xdr/io-xdr-min.js
new file mode 100644
index 000000000..9be872c99
--- /dev/null
+++ b/js/yui3/io-xdr/io-xdr-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("io-xdr",function(e,t){function a(e,t,n){var r='<object id="io_swf" type="application/x-shockwave-flash" data="'+e+'" width="0" height="0">'+'<param name="movie" value="'+e+'">'+'<param name="FlashVars" value="yid='+t+"&uid="+n+'">'+'<param name="allowScriptAccess" value="always">'+"</object>",i=s.createElement("div");s.body.appendChild(i),i.innerHTML=r}function f(t,n,r){return n==="flash"&&(t.c.responseText=decodeURI(t.c.responseText)),r==="xml"&&(t.c.responseXML=e.DataType.XML.parse(t.c.responseText)),t}function l(e,t){return e.c.abort(e.id,t)}function c(e){return u?i[e.id]!==4:e.c.isInProgress(e.id)}var n=e.publish("io:xdrReady",{fireOnce:!0}),r={},i={},s=e.config.doc,o=e.config.win,u=o&&o.XDomainRequest;e.mix(e.IO.prototype,{_transport:{},_ieEvt:function(e,t){var n=this,r=e.id,s="timeout";e.c.onprogress=function(){i[r]=3},e.c.onload=function(){i[r]=4,n.xdrResponse("success",e,t)},e.c.onerror=function(){i[r]=4,n.xdrResponse("failure",e,t)},t[s]&&(e.c.ontimeout=function(){i[r]=4,n.xdrResponse(s,e,t)},e.c[s]=t[s])},xdr:function(t,n,i){var s=this;return i.xdr.use==="flash"?(r[n.id]=i,o.setTimeout(function(){try{n.c.send(t,{id:n.id,uid:n.uid,method:i.method,data:i.data,headers:i.headers})}catch(e){s.xdrResponse("transport error",n,i),delete r[n.id]}},e.io.xdr.delay)):u?(s._ieEvt(n,i),n.c.open(i.method||"GET",t),n.c.send(i.data)):n.c.send(t,n,i),{id:n.id,abort:function(){return n.c?l(n,i):!1},isInProgress:function(){return n.c?c(n.id):!1},io:s}},xdrResponse:function(e,t,n){n=r[t.id]?r[t.id]:n;var s=this,o=u?i:r,a=n.xdr.use,l=n.xdr.dataType;switch(e){case"start":s.start(t,n);break;case"success":s.success(f(t,a,l),n),delete o[t.id];break;case"timeout":case"abort":case"transport error":t.c={status:0,statusText:e};case"failure":s.failure(f(t,a,l),n),delete o[t.id]}},_xdrReady:function(t,r){e.fire(n,t,r)},transport:function(t){t.id==="flash"&&(a(e.UA.ie?t.src+"?d="+(new Date).valueOf().toString():t.src,e.id,t.uid),e.IO.transports.flash=function(){return s.getElementById("io_swf")})}}),e.io.xdrReady=function(t,n){var r=e.io._map[n];e.io.xdr.delay=0,r._xdrReady.apply(r,[t,n])},e.io.xdrResponse=function(t,n,r){var i=e.io._map[n.uid];i.xdrResponse.apply(i,[t,n,r])},e.io.transport=function(t){var n=e.io._map["io:0"]||new e.IO;t.uid=n._uid,n.transport.apply(n,[t])},e.io.xdr={delay:100}},"3.7.3",{requires:["io-base","datatype-xml-parse"]});
diff --git a/js/yui3/io-xdr/io.swf b/js/yui3/io-xdr/io.swf
new file mode 100644
index 000000000..dc1e59ebd
--- /dev/null
+++ b/js/yui3/io-xdr/io.swf
Binary files differ
diff --git a/js/yui3/json-parse/json-parse-min.js b/js/yui3/json-parse/json-parse-min.js
new file mode 100644
index 000000000..3b87e2f16
--- /dev/null
+++ b/js/yui3/json-parse/json-parse-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("json-parse",function(e,t){function n(t){var n=typeof global=="object"?global:undefined;return(e.UA.nodejs&&n?n:e.config.win||{})[t]}function d(e,t){return e==="ok"?!0:t}var r=n("JSON"),i=Object.prototype.toString.call(r)==="[object JSON]"&&r,s=!!i,o=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,u=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,a=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,f=/(?:^|:|,)(?:\s*\[)+/g,l=/[^\],:{}\s]/,c=function(e){return"\\u"+("0000"+(+e.charCodeAt(0)).toString(16)).slice(-4)},h=function(e,t){var n=function(e,r){var i,s,o=e[r];if(o&&typeof o=="object")for(i in o)o.hasOwnProperty(i)&&(s=n(o,i),s===undefined?delete o[i]:o[i]=s);return t.call(e,r,o)};return typeof t=="function"?n({"":e},""):e},p=function(e,t){e=e.replace(o,c);if(!l.test(e.replace(u,"@").replace(a,"]").replace(f,"")))return h(eval("("+e+")"),t);throw new SyntaxError("JSON.parse")};e.namespace("JSON").parse=function(t,n){return typeof t!="string"&&(t+=""),i&&e.JSON.useNativeParse?i.parse(t,n):p(t,n)};if(i)try{s=i.parse('{"ok":false}',d).ok}catch(v){s=!1}e.JSON.useNativeParse=s},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/json-stringify/json-stringify-min.js b/js/yui3/json-stringify/json-stringify-min.js
new file mode 100644
index 000000000..82c3a7c60
--- /dev/null
+++ b/js/yui3/json-stringify/json-stringify-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("json-stringify",function(e,t){function n(t){var n=typeof global=="object"?global:undefined;return(e.UA.nodejs&&n?n:e.config.win||{})[t]}function B(e){var t=typeof e;return y[t]||y[a.call(e)]||(t===h?e?h:p:c)}function j(e){return D[e]||(D[e]="\\u"+("0000"+(+e.charCodeAt(0)).toString(16)).slice(-4),P[e]=0),++P[e]===H&&(M.push([new RegExp(e,"g"),D[e]]),_=M.length),D[e]}function F(e){var t,n;for(t=0;t<_;t++)n=M[t],e=e.replace(n[0],n[1]);return A+e.replace(O,j)+A}function I(e,t){return e.replace(/^/gm,t)}function q(t,n,r){function M(e,t){var a=e[t],f=B(a),y=[],A=r?L:k,O,_,D,P,H;o(a)&&s(a.toJSON)?a=a.toJSON(t):f===g&&(a=l(a)),s(i)&&(a=i.call(e,t,a)),a!==e[t]&&(f=B(a));switch(f){case g:case h:break;case d:return F(a);case v:return isFinite(a)?a+b:p;case m:return a+b;case p:return p;default:return undefined}for(_=c.length-1;_>=0;--_)if(c[_]===a)throw new Error("JSON.stringify. Cyclical reference");O=u(a),c.push(a);if(O)for(_=a.length-1;_>=0;--_)y[_]=M(a,_)||p;else{D=n||a,_=0;for(P in D)D.hasOwnProperty(P)&&(H=M(a,P),H&&(y[_++]=F(P)+A+H))}return c.pop(),r&&y.length?O?S+C+I(y.join(N),r)+C+x:w+C+I(y.join(N),r)+C+E:O?S+y.join(T)+x:w+y.join(T)+E}if(t===undefined)return undefined;var i=s(n)?n:null,f=a.call(r).match(/String|Number/)||[],l=e.JSON.dateToString,c=[],y,A,O;P={},H=e.JSON.charCacheThreshold;if(i||!u(n))n=undefined;if(n){y={};for(A=0,O=n.length;A<O;++A)y[n[A]]=!0;n=y}return r=f[0]==="Number"?(new Array(Math.min(Math.max(0,r),10)+1)).join(" "):(r||b).slice(0,10),M({"":t},"")}var r=n("JSON"),i=e.Lang,s=i.isFunction,o=i.isObject,u=i.isArray,a=Object.prototype.toString,f=a.call(r)==="[object JSON]"&&r,l=!!f,c="undefined",h="object",p="null",d="string",v="number",m="boolean",g="date",y={"undefined":c,string:d,"[object String]":d,number:v,"[object Number]":v,"boolean":m,"[object Boolean]":m,"[object Date]":g,"[object RegExp]":h},b="",w="{",E="}",S="[",x="]",T=",",N=",\n",C="\n",k=":",L=": ",A='"',O=/[\x00-\x07\x0b\x0e-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,M=[[/\\/g,"\\\\"],[/\"/g,'\\"'],[/\x08/g,"\\b"],[/\x09/g,"\\t"],[/\x0a/g,"\\n"],[/\x0c/g,"\\f"],[/\x0d/g,"\\r"]],_=M.length,D={},P,H;if(f)try{l="0"===f.stringify(0)}catch(R){l=!1}e.mix(e.namespace("JSON"),{useNativeStringify:l,dateToString:function(e){function t(e){return e<10?"0"+e:e}return e.getUTCFullYear()+"-"+t(e.getUTCMonth()+1)+"-"+t(e.getUTCDate())+"T"+t(e.getUTCHours())+k+t(e.getUTCMinutes())+k+t(e.getUTCSeconds())+"Z"},stringify:function(t,n,r){return f&&e.JSON.useNativeStringify?f.stringify(t,n,r):q(t,n,r)},charCacheThreshold:100})},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/jsonp-url/jsonp-url-min.js b/js/yui3/jsonp-url/jsonp-url-min.js
new file mode 100644
index 000000000..dc43afb63
--- /dev/null
+++ b/js/yui3/jsonp-url/jsonp-url-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("jsonp-url",function(e,t){var n=e.JSONPRequest,r=e.Object.getValue,i=function(){};e.mix(n.prototype,{_pattern:/\bcallback=(.*?)(?=&|$)/i,_template:"callback={callback}",_defaultCallback:function(t){var n=t.match(this._pattern),s=[],o=0,u,a,f;if(n){u=n[1].replace(/\[(['"])(.*?)\1\]/g,function(e,t,n){return s[o]=n,".@"+o++}).replace(/\[(\d+)\]/g,function(e,t){return s[o]=parseInt(t,10)|0,".@"+o++}).replace(/^\./,"");if(!/[^\w\.\$@]/.test(u)){a=u.split(".");for(o=a.length-1;o>=0;--o)a[o].charAt(0)==="@"&&(a[o]=s[parseInt(a[o].substr(1),10)]);f=r(e.config.win,a)||r(e,a)||r(e,a.slice(1))}}return f||i},_format:function(e,t){var n=this._template.replace(/\{callback\}/,t),r;return this._pattern.test(e)?e.replace(this._pattern,n):(r=e.slice(-1),r!=="&"&&r!=="?"&&(e+=e.indexOf("?")>-1?"&":"?"),e+n)}},!0)},"3.7.3",{requires:["jsonp"]});
diff --git a/js/yui3/jsonp/jsonp-min.js b/js/yui3/jsonp/jsonp-min.js
new file mode 100644
index 000000000..e0bf4b5f5
--- /dev/null
+++ b/js/yui3/jsonp/jsonp-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("jsonp",function(e,t){function r(){this._init.apply(this,arguments)}var n=e.Lang.isFunction;r.prototype={_init:function(t,r){this.url=t,this._requests={},this._timeouts={},r=n(r)?{on:{success:r}}:r||{};var i=r.on||{};i.success||(i.success=this._defaultCallback(t,r)),this._config=e.merge({context:this,args:[],format:this._format,allowCache:!1},r,{on:i})},_defaultCallback:function(){},send:function(){function u(e,r){return n(e)?function(n){var o=!0,u="_requests";r?(++t._timeouts[s],--t._requests[s]):(t._requests[s]||(o=!1,u="_timeouts"),--t[u][s]),!t._requests[s]&&!t._timeouts[s]&&delete YUI.Env.JSONP[s],o&&e.apply(i.context,[n].concat(i.args))}:null}var t=this,r=e.Array(arguments,0,!0),i=t._config,s=t._proxy||e.guid(),o;return i.allowCache&&(t._proxy=s),t._requests[s]===undefined&&(t._requests[s]=0),t._timeouts[s]===undefined&&(t._timeouts[s]=0),t._requests[s]++,r.unshift(t.url,"YUI.Env.JSONP."+s),o=i.format.apply(t,r),i.on.success?(YUI.Env.JSONP[s]=u(i.on.success),e.Get.script(o,{onFailure:u(i.on.failure),onTimeout:u(i.on.timeout,!0),timeout:i.timeout,charset:i.charset,attributes:i.attributes}),t):t},_format:function(e,t){return e.replace(/\{callback\}/,t)}},e.JSONPRequest=r,e.jsonp=function(t,n){var r=new e.JSONPRequest(t,n);return r.send.apply(r,e.Array(arguments,2,!0))},YUI.Env.JSONP||(YUI.Env.JSONP={})},"3.7.3",{requires:["get","oop"]});
diff --git a/js/yui3/lazy-model-list/lazy-model-list-min.js b/js/yui3/lazy-model-list/lazy-model-list-min.js
new file mode 100644
index 000000000..f6b89efc1
--- /dev/null
+++ b/js/yui3/lazy-model-list/lazy-model-list-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("lazy-model-list",function(e,t){var n=e.Attribute.prototype,r=YUI.namespace("Env.Model"),i=e.Lang,s=e.Array,o="add",u="error",a="reset";e.LazyModelList=e.Base.create("lazyModelList",e.ModelList,[],{free:function(e){var t;return e?(t=i.isNumber(e)?e:this.indexOf(e),t>=0&&delete this._models[t]):this._models=[],this},get:function(e){return this.attrAdded(e)?n.get.apply(this,arguments):s.map(this._items,function(t){return t[e]})},getAsHTML:function(t){return this.attrAdded(t)?e.Escape.html(n.get.apply(this,arguments)):s.map(this._items,function(n){return e.Escape.html(n[t])})},getAsURL:function(e){return this.attrAdded(e)?encodeURIComponent(n.get.apply(this,arguments)):s.map(this._items,function(t){return encodeURIComponent(t[e])})},indexOf:function(e){return s.indexOf(e&&e._isYUIModel?this._models:this._items,e)},reset:function(t,n){t||(t=[]),n||(n={});var r=e.merge({src:"reset"},n);return t=t._isYUIModelList?t.map(this._modelToObject):s.map(t,this._modelToObject),r.models=t,n.silent?this._defResetFn(r):(this.comparator&&t.sort(e.bind(this._sort,this)),this.fire(a,r)),this},revive:function(e){var t,n,r;if(e||e===0)return this._revive(i.isNumber(e)?e:this.indexOf(e));r=[];for(t=0,n=this._items.length;t<n;t++)r.push(this._revive(t));return r},toJSON:function(){return this.toArray()},_add:function(t,n){var r;n||(n={}),t=this._modelToObject(t),"clientId"in t||(t.clientId=this._generateClientId());if(this._isInList(t)){this.fire(u,{error:"Model is already in the list.",model:t,src:"add"});return}return r=e.merge(n,{index:"index"in n?n.index:this._findIndex(t),model:t}),n.silent?this._defAddFn(r):this.fire(o,r),t},_clear:function(){s.each(this._models,this._detachList,this),this._clientIdMap={},this._idMap={},this._items=[],this._models=[]},_generateClientId:function(){return r.lastId||(r.lastId=0),this.model.NAME+"_"+(r.lastId+=1)},_isInList:function(e){return!!("clientId"in e&&this._clientIdMap[e.clientId]||"id"in e&&this._idMap[e.id])},_modelToObject:function(e){return e._isYUIModel&&(e=e.getAttrs(),delete e.destroyed,delete e.initialized),e},_remove:function(t,n){return t._isYUIModel&&(t=this.indexOf(t)),e.ModelList.prototype._remove.call(this,t,n)},_revive:function(e){var t,n;return e<0?null:(t=this._items[e],t?(n=this._models[e],n||(n=new this.model(t),this._attachList(n),this._models[e]=n),n):null)},_defAddFn:function(e){var t=e.model;this._clientIdMap[t.clientId]=t,i.isValue(t.id)&&(this._idMap[t.id]=t),this._items.splice(e.index,0,t)},_defRemoveFn:function(e){var t=e.index,n=e.model,r=this._models[t];delete this._clientIdMap[n.clientId],"id"in n&&delete this._idMap[n.id],r&&this._detachList(r),this._items.splice(t,1),this._models.splice(t,1)}})},"3.7.3",{requires:["model-list"]});
diff --git a/js/yui3/loader-base/loader-base-min.js b/js/yui3/loader-base/loader-base-min.js
new file mode 100644
index 000000000..d3ad5f1a4
--- /dev/null
+++ b/js/yui3/loader-base/loader-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("loader-base",function(e,t){YUI.Env[e.version]||function(){var t=e.version,n="/build/",r=t+n,i=e.Env.base,s="gallery-2012.10.10-19-59",o="2in3",u="4",a="2.9.0",f=i+"combo?",l={version:t,root:r,base:e.Env.base,comboBase:f,skin:{defaultSkin:"sam",base:"assets/skins/",path:"skin.css",after:["cssreset","cssfonts","cssgrids","cssbase","cssreset-context","cssfonts-context"]},groups:{},patterns:{}},c=l.groups,h=function(e,t,r){var s=o+"."+(e||u)+"/"+(t||a)+n,l=r&&r.base?r.base:i,h=r&&r.comboBase?r.comboBase:f;c.yui2.base=l+s,c.yui2.root=s,c.yui2.comboBase=h},p=function(e,t){var r=(e||s)+n,o=t&&t.base?t.base:i,u=t&&t.comboBase?t.comboBase:f;c.gallery.base=o+r,c.gallery.root=r,c.gallery.comboBase=u};c[t]={},c.gallery={ext:!1,combine:!0,comboBase:f,update:p,patterns:{"gallery-":{},"lang/gallery-":{},"gallerycss-":{type:"css"}}},c.yui2={combine:!0,ext:!1,comboBase:f,update:h,patterns:{"yui2-":{configFn:function(e){/-skin|reset|fonts|grids|base/.test(e.name)&&(e.type="css",e.path=e.path.replace(/\.js/,".css"),e.path=e.path.replace(/\/yui2-skin/,"/assets/skins/sam/yui2-skin"))}}}},p(),h(),YUI.Env[t]=l}();var n={},r=[],i=1024,s=YUI.Env,o=s._loaded,u="css",a="js",f="intl",l="sam",c=e.version,h="",p=e.Object,d=p.each,v=e.Array,m=s._loaderQueue,g=s[c],y="skin-",b=e.Lang,w=s.mods,E,S=function(e,t,n,r){var i=e+"/"+t;return r||(i+="-min"),i+="."+(n||u),i};YUI.Env._cssLoaded||(YUI.Env._cssLoaded={}),e.Env.meta=g,e.Loader=function(t){var n=this;t=t||{},E=g.md5,n.context=e,n.base=e.Env.meta.base+e.Env.meta.root,n.comboBase=e.Env.meta.comboBase,n.combine=t.base&&t.base.indexOf(n.comboBase.substr(0,20))>-1,n.comboSep="&",n.maxURLLength=i,n.ignoreRegistered=t.ignoreRegistered,n.root=e.Env.meta.root,n.timeout=0,n.forceMap={},n.allowRollup=!1,n.filters={},n.required={},n.patterns={},n.moduleInfo={},n.groups=e.merge(e.Env.meta.groups),n.skin=e.merge(e.Env.meta.skin),n.conditions={},n.config=t,n._internal=!0,n._populateCache(),n.loaded=o[c],n.async=!0,n._inspectPage(),n._internal=!1,n._config(t),n.forceMap=n.force?e.Array.hash(n.force):{},n.testresults=null,e.config.tests&&(n.testresults=e.config.tests),n.sorted=[],n.dirty=!0,n.inserted={},n.skipped={},n.tested={},n.ignoreRegistered&&n._resetModules()},e.Loader.prototype={_populateCache:function(){var t=this,n=g.modules,r=s._renderedMods,i;if(r&&!t.ignoreRegistered){for(i in r)r.hasOwnProperty(i)&&(t.moduleInfo[i]=e.merge(r[i]));r=s._conditions;for(i in r)r.hasOwnProperty(i)&&(t.conditions[i]=e.merge(r[i]))}else for(i in n)n.hasOwnProperty(i)&&t.addModule(n[i],i)},_resetModules:function(){var e=this,t,n,r,i,s;for(t in e.moduleInfo)if(e.moduleInfo.hasOwnProperty(t)){r=e.moduleInfo[t],i=r.name,s=YUI.Env.mods[i]?YUI.Env.mods[i].details:null,s&&(e.moduleInfo[i]._reset=!0,e.moduleInfo[i].requires=s.requires||[],e.moduleInfo[i].optional=s.optional||[],e.moduleInfo[i].supersedes=s.supercedes||[]);if(r.defaults)for(n in r.defaults)r.defaults.hasOwnProperty(n)&&r[n]&&(r[n]=r.defaults[n]);delete r.langCache,delete r.skinCache,r.skinnable&&e._addSkin(e.skin.defaultSkin,r.name)}},REGEX_CSS:/\.css(?:[?;].*)?$/i,FILTER_DEFS:{RAW:{searchExp:"-min\\.js",replaceStr:".js"},DEBUG:{searchExp:"-min\\.js",replaceStr:"-debug.js"},COVERAGE:{searchExp:"-min\\.js",replaceStr:"-coverage.js"}},_inspectPage:function(){var e=this,t,n,r,i,s;for(s in e.moduleInfo)e.moduleInfo.hasOwnProperty(s)&&(t=e.moduleInfo[s],t.type&&t.type===u&&e.isCSSLoaded(t.name)&&(e.loaded[s]=!0));for(s in w)w.hasOwnProperty(s)&&(t=w[s],t.details&&(n=e.moduleInfo[t.name],r=t.details.requires,i=n&&n.requires,n?!n._inspected&&r&&i.length!==r.length&&delete n.expanded:n=e.addModule(t.details,s),n._inspected=!0))},_requires:function(e,t){var n,r,i,s,o=this.moduleInfo,a=o[e],f=o[t];if(!a||!f)return!1;r=a.expanded_map,i=a.after_map;if(i&&t in i)return!0;i=f.after_map;if(i&&e in i)return!1;s=o[t]&&o[t].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(e,s[n]))return!0;s=o[e]&&o[e].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(t,s[n]))return!1;return r&&t in r?!0:a.ext&&a.type===u&&!f.ext&&f.type===u?!0:!1},_config:function(t){var n,r,i,s,o,u,a,f=this,l=[],c;if(t)for(n in t)if(t.hasOwnProperty(n)){i=t[n];if(n==="require")f.require(i);else if(n==="skin")typeof i=="string"&&(f.skin.defaultSkin=t.skin,i={defaultSkin:i}),e.mix(f.skin,i,!0);else if(n==="groups"){for(r in i)if(i.hasOwnProperty(r)){a=r,u=i[r],f.addGroup(u,a);if(u.aliases)for(s in u.aliases)u.aliases.hasOwnProperty(s)&&f.addAlias(u.aliases[s],s)}}else if(n==="modules")for(r in i)i.hasOwnProperty(r)&&f.addModule(i[r],r);else if(n==="aliases")for(r in i)i.hasOwnProperty(r)&&f.addAlias(i[r],r);else n==="gallery"?this.groups.gallery.update(i,t):n==="yui2"||n==="2in3"?this.groups.yui2.update(t["2in3"],t.yui2,t):f[n]=i}o=f.filter,b.isString(o)&&(o=o.toUpperCase(),f.filterName=o,f.filter=f.FILTER_DEFS[o],o==="DEBUG"&&f.require("yui-log","dump"));if(f.filterName&&f.coverage&&f.filterName==="COVERAGE"&&b.isArray(f.coverage)&&f.coverage.length){for(n=0;n<f.coverage.length;n++)c=f.coverage[n],f.moduleInfo[c]&&f.moduleInfo[c].use?l=[].concat(l,f.moduleInfo[c].use):l.push(c);f.filters=f.filters||{},e.Array.each(l,function(e){f.filters[e]=f.FILTER_DEFS.COVERAGE}),f.filterName="RAW",f.filter=f.FILTER_DEFS[f.filterName]}},formatSkin:function(e,t){var n=y+e;return t&&(n=n+"-"+t),n},_addSkin:function(e,t,n){var r,i,s,o,u=this.moduleInfo,a=this.skin,f=u[t]&&u[t].ext;return t&&(s=this.formatSkin(e,t),u[s]||(r=u[t],i=r.pkg||t,o={skin:!0,name:s,group:r.group,type:"css",after:a.after,path:(n||i)+"/"+a.base+e+"/"+t+".css",ext:f},r.base&&(o.base=r.base),r.configFn&&(o.configFn=r.configFn),this.addModule(o,s))),s},addAlias:function(e,t){YUI.Env.aliases[t]=e,this.addModule({name:t,use:e})},addGroup:function(e,t){var n=e.modules,r=this,i,s;t=t||e.name,e.name=t,r.groups[t]=e;if(e.patterns)for(i in e.patterns)e.patterns.hasOwnProperty(i)&&(e.patterns[i].group=t,r.patterns[i]=e.patterns[i]);if(n)for(i in n)n.hasOwnProperty(i)&&(s=n[i],typeof s=="string"&&(s={name:i,fullpath:s}),s.group=t,r.addModule(s,i))},addModule:function(t,n){n=n||t.name,typeof t=="string"&&(t={name:n,fullpath:t});var r,i,o,f,l,c,p,d,m,g,y,b,w,E,x,T,N,C,k,L,A,O,M=this.conditions,_;this.moduleInfo[n]&&this.moduleInfo[n].temp&&(t=e.merge(this.moduleInfo[n],t)),t.name=n;if(!t||!t.name)return null;t.type||(t.type=a,O=t.path||t.fullpath,O&&this.REGEX_CSS.test(O)&&(t.type=u)),!t.path&&!t.fullpath&&(t.path=S(n,n,t.type)),t.supersedes=t.supersedes||t.use,t.ext="ext"in t?t.ext:this._internal?!1:!0,r=t.submodules,this.moduleInfo[n]=t,t.requires=t.requires||[];if(this.requires)for(i=0;i<this.requires.length;i++)t.requires.push(this.requires[i]);if(t.group&&this.groups&&this.groups[t.group]){A=this.groups[t.group];if(A.requires)for(i=0;i<A.requires.length;i++)t.requires.push(A.requires[i])}t.defaults||(t.defaults={requires:t.requires?[].concat(t.requires):null,supersedes:t.supersedes?[].concat(t.supersedes):null,optional:t.optional?[].concat(t.optional):null}),t.skinnable&&t.ext&&t.temp&&(k=this._addSkin(this.skin.defaultSkin,n),t.requires.unshift(k)),t.requires.length&&(t.requires=this.filterRequires(t.requires)||[]);if(!t.langPack&&t.lang){y=v(t.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b))}if(r){l=t.supersedes||[],o=0;for(i in r)if(r.hasOwnProperty(i)){c=r[i],c.path=c.path||S(n,i,t.type),c.pkg=n,c.group=t.group,c.supersedes&&(l=l.concat(c.supersedes)),p=this.addModule(c,i),l.push(i);if(p.skinnable){t.skinnable=!0,C=this.skin.overrides;if(C&&C[i])for(g=0;g<C[i].length;g++)k=this._addSkin(C[i][g],i,n),l.push(k);k=this._addSkin(this.skin.defaultSkin,i,n),l.push(k)}if(c.lang&&c.lang.length){y=v(c.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),w=this.getLangPackName(T,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),E=E||v.hash(p.supersedes),w in E||p.supersedes.push(w),t.lang=t.lang||[],x=x||v.hash(t.lang),T in x||t.lang.push(T),b=this.getLangPackName(h,n),w=this.getLangPackName(h,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),w in E||p.supersedes.push(w)}o++}t.supersedes=v.dedupe(l),this.allowRollup&&(t.rollup=o<4?o:Math.min(o-1,4))}d=t.plugins;if(d)for(i in d)d.hasOwnProperty(i)&&(m=d[i],m.pkg=n,m.path=m.path||S(n,i,t.type),m.requires=m.requires||[],m.group=t.group,this.addModule(m,i),t.skinnable&&this._addSkin(this.skin.defaultSkin,i,n));if(t.condition){f=t.condition.trigger,YUI.Env.aliases[f]&&(f=YUI.Env.aliases[f]),e.Lang.isArray(f)||(f=[f]);for(i=0;i<f.length;i++)_=f[i],L=t.condition.when,M[_]=M[_]||{},M[_][n]=t.condition,L&&L!=="after"?L==="instead"&&(t.supersedes=t.supersedes||[],t.supersedes.push(_)):(t.after=t.after||[],t.after.push(_))}return t.supersedes&&(t.supersedes=this.filterRequires(t.supersedes)),t.after&&(t.after=this.filterRequires(t.after),t.after_map=v.hash(t.after)),t.configFn&&(N=t.configFn(t),N===!1&&(delete this.moduleInfo[n],delete s._renderedMods[n],t=null)),t&&(s._renderedMods||(s._renderedMods={}),s._renderedMods[n]=e.mix(s._renderedMods[n]||{},t),s._conditions=M),t},require:function(t){var n=typeof t=="string"?v(arguments):t;this.dirty=!0,this.required=e.merge(this.required,v.hash(this.filterRequires(n))),this._explodeRollups()},_explodeRollups:function(){var e=this,t,n,r,i,s,o,u,a=e.required;if(!e.allowRollup){for(r in a)if(a.hasOwnProperty(r)){t=e.getModule(r);if(t&&t.use){o=t.use.length;for(i=0;i<o;i++){n=e.getModule(t.use[i]);if(n&&n.use){u=n.use.length;for(s=0;s<u;s++)a[n.use[s]]=!0}else a[t.use[i]]=!0}}}e.required=a}},filterRequires:function(t){if(t){e.Lang.isArray(t)||(t=[t]),t=e.Array(t);var n=[],r,i,s,o;for(r=0;r<t.length;r++){i=this.getModule(t[r]);if(i&&i.use)for(s=0;s<i.use.length;s++)o=this.getModule(i.use[s]),o&&o.use&&o.name!==i.name?n=e.Array.dedupe([].concat(n,this.filterRequires(o.use))):n.push(i.use[s]);else n.push(t[r])}t=n}return t},getRequires:function(t){if(!t)return r;if(t._parsed)return t.expanded||r;var n,i,s,o,u,a,l=this.testresults,c=t.name,m,g=w[c]&&w[c].details,y,b,E,S,x,T,N,C,k,L,A=t.lang||t.intl,O=this.moduleInfo,M=e.Features&&e.Features.tests.load,_,D;t.temp&&g&&(x=t,t=this.addModule(g,c),t.group=x.group,t.pkg=x.pkg,delete t.expanded),D=!!this.lang&&t.langCache!==this.lang||t.skinCache!==this.skin.defaultSkin;if(t.expanded&&!D)return t.expanded;y=[],_={},S=this.filterRequires(t.requires),t.lang&&(y.unshift("intl"),S.unshift("intl"),A=!0),T=this.filterRequires(t.optional),t._parsed=!0,t.langCache=this.lang,t.skinCache=this.skin.defaultSkin;for(n=0;n<S.length;n++)if(!_[S[n]]){y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}S=this.filterRequires(t.supersedes);if(S)for(n=0;n<S.length;n++)if(!_[S[n]]){t.submodules&&y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}if(T&&this.loadOptional)for(n=0;n<T.length;n++)if(!_[T[n]]){y.push(T[n]),_[T[n]]=!0,i=O[T[n]];if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}m=this.conditions[c];if(m){t._parsed=!1;if(l&&M)d(l,function(e,t){var n=M[t].name;!_[n]&&M[t].trigger===c&&e&&M[t]&&(_[n]=!0,y.push(n))});else for(n in m)if(m.hasOwnProperty(n)&&!_[n]){E=m[n],b=E&&(!E.ua&&!E.test||E.ua&&e.UA[E.ua]||E.test&&E.test(e,S));if(b){_[n]=!0,y.push(n),i=this.getModule(n);if(i){o=this.getRequires(i);for(s=0;s<o.length;s++)y.push(o[s])}}}}if(t.skinnable){C=this.skin.overrides;for(n in YUI.Env.aliases)YUI.Env.aliases.hasOwnProperty(n)&&e.Array.indexOf(YUI.Env.aliases[n],c)>-1&&(k=n);if(C&&(C[c]||k&&C[k])){L=c,C[k]&&(L=k);for(n=0;n<C[L].length;n++)N=this._addSkin(C[L][n],c),this.isCSSLoaded(N,this._boot)||y.push(N)}else N=this._addSkin(this.skin.defaultSkin,c),this.isCSSLoaded(N,this._boot)||y.push(N)}return t._parsed=!1,A&&(t.lang&&!t.langPack&&e.Intl&&(a=e.Intl.lookupBestLang(this.lang||h,t.lang),u=this.getLangPackName(a,c),u&&y.unshift(u)),y.unshift(f)),t.expanded_map=v.hash(y),t.expanded=p.keys(t.expanded_map),t.expanded},isCSSLoaded:function(t,n){if(!t||!YUI.Env.cssStampEl||!n&&this.ignoreRegistered)return!1;var r=YUI.Env.cssStampEl,i=!1,s=YUI.Env._cssLoaded[t],o=r.currentStyle;return s!==undefined?s:(r.className=t,o||(o=e.config.doc.defaultView.getComputedStyle(r,null)),o&&o.display==="none"&&(i=!0),r.className="",YUI.Env._cssLoaded[t]=i,i)},getProvides:function(t){var r=this.getModule(t),i,s;return r?(r&&!r.provides&&(i={},s=r.supersedes,s&&v.each(s,function(t){e.mix(i,this.getProvides(t))},this),i[t]=!0,r.provides=i),r.provides):n},calculate:function(e,t){if(e||t||this.dirty)e&&this._config(e),this._init||this._setup(),this._explode(),this.allowRollup?this._rollup():this._explodeRollups(),this._reduce(),this._sort()},_addLangPack:function(t,n,r){var i=n.name,s,o,u=this.moduleInfo[r];return u||(s=S(n.pkg||i,r,a,!0),o={path:s,intl:!0,langPack:!0,ext:n.ext,group:n.group,supersedes:[]},n.root&&(o.root=n.root),n.base&&(o.base=n.base),n.configFn&&(o.configFn=n.configFn),this.addModule(o,r),t&&(e.Env.lang=e.Env.lang||{},e.Env.lang[t]=e.Env.lang[t]||{},e.Env.lang[t][i]=!0)),this.moduleInfo[r]},_setup:function(){var t=this.moduleInfo,n,r,i,o,u,a;for(n in t)t.hasOwnProperty(n)&&(o=t[n],o&&(o.requires=v.dedupe(o.requires),o.lang&&(a=this.getLangPackName(h,n),this._addLangPack(null,o,a))));u={},this.ignoreRegistered||e.mix(u,s.mods),this.ignore&&e.mix(u,v.hash(this.ignore));for(i in u)u.hasOwnProperty(i)&&e.mix(u,this.getProvides(i));if(this.force)for(r=0;r<this.force.length;r++)this.force[r]in u&&delete u[this.force[r]];e.mix(this.loaded,u),this._init=!0},getLangPackName:function(e,t){return"lang/"+t+(e?"_"+e:"")},_explode:function(){var t=this.required,n,r,i={},s=this,o,u;s.dirty=!1,s._explodeRollups(),t=s.required;for(o in t)t.hasOwnProperty(o)&&(i[o]||(i[o]=!0,n=s.getModule(o),n&&(u=n.expound,u&&(t[u]=s.getModule(u),r=s.getRequires(t[u]),e.mix(t,v.hash(r))),r=s.getRequires(n),e.mix(t,v.hash(r)))))},_patternTest:function(e,t){return e.indexOf(t)>-1},getModule:function(t){if(!t)return null;var n,r,i,s=this.moduleInfo[t],o=this.patterns;if(!s||s&&s.ext)for(i in o)if(o.hasOwnProperty(i)){n=o[i],n.test||(n.test=this._patternTest);if(n.test(t,i)){r=n;break}}return s?r&&s&&r.configFn&&!s.configFn&&(s.configFn=r.configFn,s.configFn(s)):r&&(n.action?n.action.call(this,t,i):(s=this.addModule(e.merge(r),t),r.configFn&&(s.configFn=r.configFn),s.temp=!0)),s},_rollup:function(){},_reduce:function(e){e=e||this.required;var t,n,r,i,s=this.loadType,o=this.ignore?v.hash(this.ignore):!1;for(t in e)if(e.hasOwnProperty(t)){i=this.getModule(t),((this.loaded[t]||w[t])&&!this.forceMap[t]&&!this.ignoreRegistered||s&&i&&i.type!==s)&&delete e[t],o&&o[t]&&delete e[t],r=i&&i.supersedes;if(r)for(n=0;n<r.length;n++)r[n]in e&&delete e[r[n]]}return e},_finish:function(e,t){m.running=!1;var n=this.onEnd;n&&n.call(this.context,{msg:e,data:this.data,success:t}),this._continue()},_onSuccess:function(){var t=this,n=e.merge(t.skipped),r,i=[],s=t.requireRegistration,o,u,f,l;for(f in n)n.hasOwnProperty(f)&&delete t.inserted[f];t.skipped={};for(f in t.inserted)t.inserted.hasOwnProperty(f)&&(l=t.getModule(f),!l||!s||l.type!==a||f in YUI.Env.mods?e.mix(t.loaded,t.getProvides(f)):i.push(f));r=t.onSuccess,u=i.length?"notregistered":"success",o=!i.length,r&&r.call(t.context,{msg:u,data:t.data,success:o,failed:i,skipped:n}),t._finish(u,o)},_onProgress:function(e){var t=this,n;if(e.data&&e.data.length)for(n=0;n<e.data.length;n++)e.data[n]=t.getModule(e.data[n].name);t.onProgress&&t.onProgress.call(t.context,{name:e.url,data:e.data})},_onFailure:function(e){var t=this.onFailure,n=[],r=0,i=e.errors.length;for(r;r<i;r++)n.push(e.errors[r].error);n=n.join(","),t&&t.call(this.context,{msg:n,data:this.data,success:!1}),this._finish(n,!1)},_onTimeout:function(){var e=this.onTimeout;e&&e.call(this.context,{msg:"timeout",data:this.data,success:!1})},_sort:function(){var e=p.keys(this.required),t={},n=0,r,i,s,o,u,a,f;for(;;){r=e.length,a=!1;for(o=n;o<r;o++){i=e[o];for(u=o+1;u<r;u++){f=i+e[u];if(!t[f]&&this._requires(i,e[u])){s=e.splice(u,1),e.splice(o,0,s[0]),t[f]=!0,a=!0;break}}if(a)break;n++}if(!a)break}this.sorted=e},_insert:function(t,n,r,i){t&&this._config(t);var s=this.resolve(!i),o=this,f=0,l=0,c={},h,p;o._refetch=[],r&&(s[r===a?u:a]=[]),o.fetchCSS||(s.css=[]),s.js.length&&f++,s.css.length&&f++,p=function(t){l++;var n={},r=0,i=0,s="",u,a,p;if(t&&t.errors)for(r=0;r<t.errors.length;r++)t.errors[r].request?s=t.errors[r].request.url:s=t.errors[r],n[s]=s;if(t&&t.data&&t.data.length&&t.type==="success")for(r=0;r<t.data.length;r++){o.inserted[t.data[r].name]=!0;if(t.data[r].lang||t.data[r].skinnable)delete o.inserted[t.data[r].name],o._refetch.push(t.data[r].name)}if(l===f){o._loading=null;if(o._refetch.length){for(r=0;r<o._refetch.length;r++){h=o.getRequires(o.getModule(o._refetch[r]));for(i=0;i<h.length;i++)o.inserted[h[i]]||(c[h[i]]=h[i])}c=e.Object.keys(c);if(c.length){o.require(c),p=o.resolve(!0);if(p.cssMods.length){for(r=0;r<p.cssMods.length;r++)a=p.cssMods[r].name,delete YUI.Env._cssLoaded[a],o.isCSSLoaded(a)&&(o.inserted[a]=!0,delete o.required[a]);o.sorted=[],o._sort()}t=null,o._insert()}}t&&t.fn&&(u=t.fn,delete t.fn,u.call(o,t))}},this._loading=!0;if(!s.js.length&&!s.css.length){l=-1,p({fn:o._onSuccess});return}s.css.length&&e.Get.css(s.css,{data:s.cssMods,attributes:o.cssAttributes,insertBefore:o.insertBefore,charset:o.charset,timeout:o.timeout,context:o,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}}),s.js.length&&e.Get.js(s.js,{data:s.jsMods,insertBefore:o.insertBefore,attributes:o.jsAttributes,charset:o.charset,timeout:o.timeout,autopurge:!1,context:o,async:o.async,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}})},_continue:function(){!m.running&&m.size()>0&&(m.running=!0,m.next()())},insert:function(t,n,r){var i=this,s=e.merge(this);delete s.require,delete s.dirty,m.add(function(){i._insert(s,t,n,r)}),this._continue()},loadNext:function(){return},_filter:function(e,t,n){var r=this.filter,i=t&&t in this.filters,s=i&&this.filters[t],o=n||(this.moduleInfo[t]?this.moduleInfo[t].group:null);return o&&this.groups[o]&&this.groups[o].filter&&(s=this.groups[o].filter,i=!0),e&&(i&&(r=b.isString(s)?this.FILTER_DEFS[s.toUpperCase()]||null:s),r&&(e=e.replace(new RegExp(r.searchExp,"g"),r.replaceStr))),e},_url:function(e,t,n){return this._filter((n||this.base||"")+e,t)},resolve:function(e,t){var r,s,o,f,c,h,p,d,v,m,g,y,w,E,S=[],x,T,N={},C=this,k,A,O=C.ignoreRegistered?{}:C.inserted,M={js:[],jsMods:[],css:[],cssMods:[]},_=C.loadType||"js",D;(C.skin.overrides||C.skin.defaultSkin!==l||C.ignoreRegistered)&&C._resetModules(),e&&C.calculate(),t=t||C.sorted,D=function(e){if(e){c=e.group&&C.groups[e.group]||n,c.async===!1&&(e.async=c.async),f=e.fullpath?C._filter(e.fullpath,t[s]):C._url(e.path,t[s],c.base||e.base);if(e.attributes||e.async===!1)f={url:f,async:e.async},e.attributes&&(f.attributes=e.attributes);M[e.type].push(f),M[e.type+"Mods"].push(e)}},r=t.length,y=C.comboBase,f=y,m={};for(s=0;s<r;s++){v=y,o=C.getModule(t[s]),h=o&&o.group,c=C.groups[h];if(h&&c){if(!c.combine||o.fullpath){D(o);continue}o.combine=!0,c.comboBase&&(v=c.comboBase),"root"in c&&b.isValue(c.root)&&(o.root=c.root),o.comboSep=c.comboSep||C.comboSep,o.maxURLLength=c.maxURLLength||C.maxURLLength}else if(!C.combine){D(o);continue}m[v]=m[v]||[],m[v].push(o)}for(p in m)if(m.hasOwnProperty(p)){N[p]=N[p]||{js:[],jsMods:[],css:[],cssMods:[]},f=p,g=m[p],r=g.length;if(r)for(s=0;s<r;s++){if(O[g[s]])continue;o=g[s],o&&(o.combine||!o.ext)?(N[p].comboSep=o.comboSep,N[p].group=o.group,N[p].maxURLLength=o.maxURLLength,d=(b.isValue(o.root)?o.root:C.root)+(o.path||o.fullpath),d=C._filter(d,o.name),N[p][o.type].push(d),N[p][o.type+"Mods"].push(o)):g[s]&&D(g[s])}}for(p in N){w=p,k=N[w].comboSep||C.comboSep,A=N[w].maxURLLength||C.maxURLLength;for(_ in N[w])if(_===a||_===u){E=N[w][_],g=N[w][_+"Mods"],r=E.length,x=w+E.join(k),T=x.length,A<=w.length&&(A=i);if(r)if(T>A){S=[];for(t=0;t<r;t++)S.push(E[t]),x=w+S.join(k),x.length>A&&(o=S.pop(),x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)),S=[],o&&S.push(o));S.length&&(x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)))}else M[_].push(C._filter(x,null,N[w].group));M[_+"Mods"]=M[_+"Mods"].concat(g)}}return N=null,M},load:function(e){if(!e)return;var t=this,n=t.resolve(!0);t.data=n,t.onEnd=function(){e.apply(t.context||t,arguments)},t.insert()}}},"3.7.3",{requires:["get","features"]});
diff --git a/js/yui3/loader-rollup/loader-rollup-min.js b/js/yui3/loader-rollup/loader-rollup-min.js
new file mode 100644
index 000000000..d8e42d1cf
--- /dev/null
+++ b/js/yui3/loader-rollup/loader-rollup-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("loader-rollup",function(e,t){e.Loader.prototype._rollup=function(){var e,t,n,r,i=this.required,s,o=this.moduleInfo,u,a,f;if(this.dirty||!this.rollups){this.rollups={};for(e in o)o.hasOwnProperty(e)&&(n=this.getModule(e),n&&n.rollup&&(this.rollups[e]=n))}for(;;){u=!1;for(e in this.rollups)if(this.rollups.hasOwnProperty(e)&&!i[e]&&(!this.loaded[e]||this.forceMap[e])){n=this.getModule(e),r=n.supersedes||[],s=!1;if(!n.rollup)continue;a=0;for(t=0;t<r.length;t++){f=o[r[t]];if(this.loaded[r[t]]&&!this.forceMap[r[t]]){s=!1;break}if(i[r[t]]&&n.type===f.type){a++,s=a>=n.rollup;if(s)break}}s&&(i[e]=!0,u=!0,this.getRequires(n))}if(!u)break}}},"3.7.3",{requires:["loader-base"]});
diff --git a/js/yui3/loader-yui3/loader-yui3-min.js b/js/yui3/loader-yui3/loader-yui3-min.js
new file mode 100644
index 000000000..4c0abf0d7
--- /dev/null
+++ b/js/yui3/loader-yui3/loader-yui3-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("loader-yui3",function(e,t){YUI.Env[e.version].modules=YUI.Env[e.version].modules||{"align-plugin":{requires:["node-screen","node-pluginhost"]},anim:{use:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"]},"anim-base":{requires:["base-base","node-style"]},"anim-color":{requires:["anim-base"]},"anim-curve":{requires:["anim-xy"]},"anim-easing":{requires:["anim-base"]},"anim-node-plugin":{requires:["node-pluginhost","anim-base"]},"anim-scroll":{requires:["anim-base"]},"anim-shape":{requires:["anim-base","anim-easing","anim-color","matrix"]},"anim-shape-transform":{use:["anim-shape"]},"anim-xy":{requires:["anim-base","node-screen"]},app:{use:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"]},"app-base":{requires:["classnamemanager","pjax-base","router","view"]},"app-content":{requires:["app-base","pjax-content"]},"app-transitions":{requires:["app-base"]},"app-transitions-css":{type:"css"},"app-transitions-native":{condition:{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"},requires:["app-transitions","app-transitions-css","parallel","transition"]},"array-extras":{requires:["yui-base"]},"array-invoke":{requires:["yui-base"]},arraylist:{requires:["yui-base"]},"arraylist-add":{requires:["arraylist"]},"arraylist-filter":{requires:["arraylist"]},arraysort:{requires:["yui-base"]},"async-queue":{requires:["event-custom"]},attribute:{use:["attribute-base","attribute-complex"]},"attribute-base":{requires:["attribute-core","attribute-events","attribute-extras"]},"attribute-complex":{requires:["attribute-base"]},"attribute-core":{requires:["oop"]},"attribute-events":{requires:["event-custom"]},"attribute-extras":{requires:["oop"]},autocomplete:{use:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"]},"autocomplete-base":{optional:["autocomplete-sources"],requires:["array-extras","base-build","escape","event-valuechange","node-base"]},"autocomplete-filters":{requires:["array-extras","text-wordbreak"]},"autocomplete-filters-accentfold":{requires:["array-extras","text-accentfold","text-wordbreak"]},"autocomplete-highlighters":{requires:["array-extras","highlight-base"]},"autocomplete-highlighters-accentfold":{requires:["array-extras","highlight-accentfold"]},"autocomplete-list":{after:["autocomplete-sources"],lang:["en"],requires:["autocomplete-base","event-resize","node-screen","selector-css3","shim-plugin","widget","widget-position","widget-position-align"],skinnable:!0},"autocomplete-list-keys":{condition:{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"},requires:["autocomplete-list","base-build"]},"autocomplete-plugin":{requires:["autocomplete-list","node-pluginhost"]},"autocomplete-sources":{optional:["io-base","json-parse","jsonp","yql"],requires:["autocomplete-base"]},base:{use:["base-base","base-pluginhost","base-build"]},"base-base":{after:["attribute-complex"],requires:["base-core","attribute-base"]},"base-build":{requires:["base-base"]},"base-core":{requires:["attribute-core"]},"base-pluginhost":{requires:["base-base","pluginhost"]},button:{requires:["button-core","cssbutton","widget"]},"button-core":{requires:["attribute-core","classnamemanager","node-base"]},"button-group":{requires:["button-plugin","cssbutton","widget"]},"button-plugin":{requires:["button-core","cssbutton","node-pluginhost"]},cache:{use:["cache-base","cache-offline","cache-plugin"]},"cache-base":{requires:["base"]},"cache-offline":{requires:["cache-base","json"]},"cache-plugin":{requires:["plugin","cache-base"]},calendar:{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["calendar-base","calendarnavigator"],skinnable:!0},"calendar-base":{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["widget","substitute","datatype-date","datatype-date-math","cssgrids"],skinnable:!0},calendarnavigator:{requires:["plugin","classnamemanager","datatype-date","node","substitute"],skinnable:!0},charts:{requires:["charts-base"]},"charts-base":{requires:["dom","datatype-number","datatype-date","event-custom","event-mouseenter","event-touch","widget","widget-position","widget-stack","graphics"]},"charts-legend":{requires:["charts-base"]},classnamemanager:{requires:["yui-base"]},"clickable-rail":{requires:["slider-base"]},collection:{use:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"]},console:{lang:["en","es","ja"],requires:["yui-log","widget"],skinnable:!0},"console-filters":{requires:["plugin","console"],skinnable:!0},controller:{use:["router"]},cookie:{requires:["yui-base"]},"createlink-base":{requires:["editor-base"]},cssbase:{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},"cssbase-context":{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},cssbutton:{type:"css"},cssfonts:{type:"css"},"cssfonts-context":{type:"css"},cssgrids:{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-base":{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-units":{optional:["cssreset","cssfonts"],requires:["cssgrids-base"],type:"css"},cssreset:{type:"css"},"cssreset-context":{type:"css"},dataschema:{use:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"]},"dataschema-array":{requires:["dataschema-base"]},"dataschema-base":{requires:["base"]},"dataschema-json":{requires:["dataschema-base","json"]},"dataschema-text":{requires:["dataschema-base"]},"dataschema-xml":{requires:["dataschema-base"]},datasource:{use:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"]},"datasource-arrayschema":{requires:["datasource-local","plugin","dataschema-array"]},"datasource-cache":{requires:["datasource-local","plugin","cache-base"]},"datasource-function":{requires:["datasource-local"]},"datasource-get":{requires:["datasource-local","get"]},"datasource-io":{requires:["datasource-local","io-base"]},"datasource-jsonschema":{requires:["datasource-local","plugin","dataschema-json"]},"datasource-local":{requires:["base"]},"datasource-polling":{requires:["datasource-local"]},"datasource-textschema":{requires:["datasource-local","plugin","dataschema-text"]},"datasource-xmlschema":{requires:["datasource-local","plugin","datatype-xml","dataschema-xml"]},datatable:{use:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"]},"datatable-base":{requires:["datatable-core","datatable-table","datatable-head","datatable-body","base-build","widget"],skinnable:!0},"datatable-base-deprecated":{requires:["recordset-base","widget","substitute","event-mouseenter"],skinnable:!0},"datatable-body":{requires:["datatable-core","view","classnamemanager"]},"datatable-column-widths":{requires:["datatable-base"]},"datatable-core":{requires:["escape","model-list","node-event-delegate"]},"datatable-datasource":{requires:["datatable-base","plugin","datasource-local"]},"datatable-datasource-deprecated":{requires:["datatable-base-deprecated","plugin","datasource-local"]},"datatable-deprecated":{use:["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"]},"datatable-head":{requires:["datatable-core","view","classnamemanager"]},"datatable-message":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-mutable":{requires:["datatable-base"]},"datatable-scroll":{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0},"datatable-scroll-deprecated":{requires:["datatable-base-deprecated","plugin"]},"datatable-sort":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-sort-deprecated":{lang:["en"],requires:["datatable-base-deprecated","plugin","recordset-sort"]},"datatable-table":{requires:["datatable-core","datatable-head","datatable-body","view","classnamemanager"]},datatype:{use:["datatype-date","datatype-number","datatype-xml"]},"datatype-date":{use:["datatype-date-parse","datatype-date-format","datatype-date-math"]},"datatype-date-format":{lang:["ar","ar-JO","ca","ca-ES","da","da-DK","de","de-AT","de-DE","el","el-GR","en","en-AU","en-CA","en-GB","en-IE","en-IN","en-JO","en-MY","en-NZ","en-PH","en-SG","en-US","es","es-AR","es-BO","es-CL","es-CO","es-EC","es-ES","es-MX","es-PE","es-PY","es-US","es-UY","es-VE","fi","fi-FI","fr","fr-BE","fr-CA","fr-FR","hi","hi-IN","id","id-ID","it","it-IT","ja","ja-JP","ko","ko-KR","ms","ms-MY","nb","nb-NO","nl","nl-BE","nl-NL","pl","pl-PL","pt","pt-BR","ro","ro-RO","ru","ru-RU","sv","sv-SE","th","th-TH","tr","tr-TR","vi","vi-VN","zh-Hans","zh-Hans-CN","zh-Hant","zh-Hant-HK","zh-Hant-TW"]},"datatype-date-math":{requires:["yui-base"]},"datatype-date-parse":{},"datatype-number":{use:["datatype-number-parse","datatype-number-format"]},"datatype-number-format":{},"datatype-number-parse":{},"datatype-xml":{use:["datatype-xml-parse","datatype-xml-format"]},"datatype-xml-format":{},"datatype-xml-parse":{},dd:{use:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"]},"dd-constrain":{requires:["dd-drag"]},"dd-ddm":{requires:["dd-ddm-base","event-resize"]},"dd-ddm-base":{requires:["node","base","yui-throttle","classnamemanager"]},"dd-ddm-drop":{requires:["dd-ddm"]},"dd-delegate":{requires:["dd-drag","dd-drop-plugin","event-mouseenter"]},"dd-drag":{requires:["dd-ddm-base"]},"dd-drop":{requires:["dd-drag","dd-ddm-drop"]},"dd-drop-plugin":{requires:["dd-drop"]},"dd-gestures":{condition:{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"},requires:["dd-drag","event-synthetic","event-gestures"]},"dd-plugin":{optional:["dd-constrain","dd-proxy"],requires:["dd-drag"]},"dd-proxy":{requires:["dd-drag"]},"dd-scroll":{requires:["dd-drag"]},dial:{lang:["en","es"],requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],skinnable:!0},dom:{use:["dom-base","dom-screen","dom-style","selector-native","selector"]},"dom-base":{requires:["dom-core"]},"dom-core":{requires:["oop","features"]},"dom-deprecated":{requires:["dom-base"]},"dom-screen":{requires:["dom-base","dom-style"]},"dom-style":{requires:["dom-base"]},"dom-style-ie":{condition:{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"},requires:["dom-style"]},dump:{requires:["yui-base"]},editor:{use:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"]},"editor-base":{requires:["base","frame","node","exec-command","editor-selection"]},"editor-bidi":{requires:["editor-base"]},"editor-br":{requires:["editor-base"]},"editor-lists":{requires:["editor-base"]},"editor-para":{requires:["editor-para-base"]},"editor-para-base":{requires:["editor-base"]},"editor-para-ie":{condition:{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"},requires:["editor-para-base"]},"editor-selection":{requires:["node"]},"editor-tab":{requires:["editor-base"]},escape:{requires:["yui-base"]},event:{after:["node-base"],use:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"]},"event-base":{after:["node-base"],requires:["event-custom-base"]},"event-base-ie":{after:["event-base"],condition:{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"},requires:["node-base"]},"event-contextmenu":{requires:["event-synthetic","dom-screen"]},"event-custom":{use:["event-custom-base","event-custom-complex"]},"event-custom-base":{requires:["oop"]},"event-custom-complex":{requires:["event-custom-base"]},"event-delegate":{requires:["node-base"]},"event-flick":{requires:["node-base","event-touch","event-synthetic"]},"event-focus":{requires:["event-synthetic"]},"event-gestures":{use:["event-flick","event-move"]},"event-hover":{requires:["event-mouseenter"]},"event-key":{requires:["event-synthetic"]},"event-mouseenter":{requires:["event-synthetic"]},"event-mousewheel":{requires:["node-base"]},"event-move":{requires:["node-base","event-touch","event-synthetic"]},"event-outside":{requires:["event-synthetic"]},"event-resize":{requires:["node-base","event-synthetic"]},"event-simulate":{requires:["event-base"]},"event-synthetic":{requires:["node-base","event-custom-complex"]},"event-tap":{requires:["node-base","event-base","event-touch","event-synthetic"]},"event-touch":{requires:["node-base"]},"event-valuechange":{requires:["event-focus","event-synthetic"]},"exec-command":{requires:["frame"]},features:{requires:["yui-base"]},file:{requires:["file-flash","file-html5"]},"file-flash":{requires:["base"]},"file-html5":{requires:["base"]},frame:{requires:["base","node","selector-css3","yui-throttle"]},"gesture-simulate":{requires:["async-queue","event-simulate","node-screen"]},get:{requires:["yui-base"]},graphics:{requires:["node","event-custom","pluginhost","matrix","classnamemanager"]},"graphics-canvas":{condition:{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"},requires:["graphics"]},"graphics-canvas-default":{condition:{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}},"graphics-svg":{condition:{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"},requires:["graphics"]},"graphics-svg-default":{condition:{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}},"graphics-vml":{condition:{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"},requires:["graphics"]},"graphics-vml-default":{condition:{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}},handlebars:{use:["handlebars-compiler"]},"handlebars-base":{requires:["escape"]},"handlebars-compiler":{requires:["handlebars-base"]},highlight:{use:["highlight-base","highlight-accentfold"]},"highlight-accentfold":{requires:["highlight-base","text-accentfold"]},"highlight-base":{requires:["array-extras","classnamemanager","escape","text-wordbreak"]},history:{use:["history-base","history-hash","history-hash-ie","history-html5"]},"history-base":{requires:["event-custom-complex"]},"history-hash":{after:["history-html5"],requires:["event-synthetic","history-base","yui-later"]},"history-hash-ie":{condition:{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"},requires:["history-hash","node-base"]},"history-html5":{optional:["json"],requires:["event-base","history-base","node-base"]},imageloader:{requires:["base-base","node-style","node-screen"]},intl:{requires:["intl-base","event-custom"]},"intl-base":{requires:["yui-base"]},io:{use:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"]},"io-base":{requires:["event-custom-base","querystring-stringify-simple"]},"io-form":{requires:["io-base","node-base"]},"io-nodejs":{condition:{name:"io-nodejs",trigger:"io-base",ua:"nodejs"},requires:["io-base"]},"io-queue":{requires:["io-base","queue-promote"]},"io-upload-iframe":{requires:["io-base","node-base"]},"io-xdr":{requires:["io-base","datatype-xml-parse"]},json:{use:["json-parse","json-stringify"]},"json-parse":{requires:["yui-base"]},"json-stringify":{requires:["yui-base"]},jsonp:{requires:["get","oop"]},"jsonp-url":{requires:["jsonp"]},"lazy-model-list":{requires:["model-list"]},loader:{use:["loader-base","loader-rollup","loader-yui3"]},"loader-base":{requires:["get","features"]},"loader-rollup":{requires:["loader-base"]},"loader-yui3":{requires:["loader-base"]},matrix:{requires:["yui-base"]},model:{requires:["base-build","escape","json-parse"]},"model-list":{requires:["array-extras","array-invoke","arraylist","base-build","escape","json-parse","model"]},"model-sync-rest":{requires:["model","io-base","json-stringify"]},node:{use:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"]},"node-base":{requires:["event-base","node-core","dom-base"]},"node-core":{requires:["dom-core","selector"]},"node-deprecated":{requires:["node-base"]},"node-event-delegate":{requires:["node-base","event-delegate"]},"node-event-html5":{requires:["node-base"]},"node-event-simulate":{requires:["node-base","event-simulate","gesture-simulate"]},"node-flick":{requires:["classnamemanager","transition","event-flick","plugin"],skinnable:!0},"node-focusmanager":{requires:["attribute","node","plugin","node-event-simulate","event-key","event-focus"]},"node-load":{requires:["node-base","io-base"]},"node-menunav":{requires:["node","classnamemanager","plugin","node-focusmanager"],skinnable:!0},"node-pluginhost":{requires:["node-base","pluginhost"]},"node-screen":{requires:["dom-screen","node-base"]},"node-scroll-info":{requires:["base-build","dom-screen","event-resize","node-pluginhost","plugin"]},"node-style":{requires:["dom-style","node-base"]},oop:{requires:["yui-base"]},overlay:{requires:["widget","widget-stdmod","widget-position","widget-position-align","widget-stack","widget-position-constrain"],skinnable:!0},panel:{requires:["widget","widget-autohide","widget-buttons","widget-modality","widget-position","widget-position-align","widget-position-constrain","widget-stack","widget-stdmod"],skinnable:!0},parallel:{requires:["yui-base"]},pjax:{requires:["pjax-base","pjax-content"]},"pjax-base":{requires:["classnamemanager","node-event-delegate","router"]},"pjax-content":{requires:["io-base","node-base","router"]},"pjax-plugin":{requires:["node-pluginhost","pjax","plugin"]},plugin:{requires:["base-base"]},pluginhost:{use:["pluginhost-base","pluginhost-config"]},"pluginhost-base":{requires:["yui-base"]},"pluginhost-config":{requires:["pluginhost-base"]},profiler:{requires:["yui-base"]},querystring:{use:["querystring-parse","querystring-stringify"]},"querystring-parse":{requires:["yui-base","array-extras"]},"querystring-parse-simple":{requires:["yui-base"]},"querystring-stringify":{requires:["yui-base"]},"querystring-stringify-simple":{requires:["yui-base"]},"queue-promote":{requires:["yui-base"]},"range-slider":{requires:["slider-base","slider-value-range","clickable-rail"]},recordset:{use:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"]},"recordset-base":{requires:["base","arraylist"]},"recordset-filter":{requires:["recordset-base","array-extras","plugin"]},"recordset-indexer":{requires:["recordset-base","plugin"]},"recordset-sort":{requires:["arraysort","recordset-base","plugin"]},resize:{use:["resize-base","resize-proxy","resize-constrain"]},"resize-base":{requires:["base","widget","event","oop","dd-drag","dd-delegate","dd-drop"],skinnable:!0},"resize-constrain":{requires:["plugin","resize-base"]},"resize-plugin":{optional:["resize-constrain"],requires:["resize-base","plugin"]},"resize-proxy":{requires:["plugin","resize-base"]},router:{optional:["querystring-parse"],requires:["array-extras","base-build","history"]},scrollview:{requires:["scrollview-base","scrollview-scrollbars"]},"scrollview-base":{requires:["widget","event-gestures","event-mousewheel","transition"],skinnable:!0},"scrollview-base-ie":{condition:{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"},requires:["scrollview-base"]},"scrollview-list":{requires:["plugin","classnamemanager"],skinnable:!0},"scrollview-paginator":{requires:["plugin","classnamemanager"]},"scrollview-scrollbars":{requires:["classnamemanager","transition","plugin"],skinnable:!0},selector:{requires:["selector-native"]},"selector-css2":{condition:{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"},requires:["selector-native"]},"selector-css3":{requires:["selector-native","selector-css2"]},"selector-native":{requires:["dom-base"]},"shim-plugin":{requires:["node-style","node-pluginhost"]},slider:{use:["slider-base","slider-value-range","clickable-rail","range-slider"]},"slider-base":{requires:["widget","dd-constrain","event-key"],skinnable:!0},"slider-value-range":{requires:["slider-base"]},sortable:{requires:["dd-delegate","dd-drop-plugin","dd-proxy"]},"sortable-scroll":{requires:["dd-scroll","sortable"]},stylesheet:{requires:["yui-base"]},substitute:{optional:["dump"],requires:["yui-base"]},swf:{requires:["event-custom","node","swfdetect","escape"]},swfdetect:{requires:["yui-base"]},tabview:{requires:["widget","widget-parent","widget-child","tabview-base","node-pluginhost","node-focusmanager"],skinnable:!0},"tabview-base":{requires:["node-event-delegate","classnamemanager","skin-sam-tabview"]},"tabview-plugin":{requires:["tabview-base"]},test:{requires:["event-simulate","event-custom","json-stringify"]},"test-console":{requires:["console-filters","test","array-extras"],skinnable:!0},text:{use:["text-accentfold","text-wordbreak"]},"text-accentfold":{requires:["array-extras","text-data-accentfold"]},"text-data-accentfold":{requires:["yui-base"]},"text-data-wordbreak":{requires:["yui-base"]},"text-wordbreak":{requires:["array-extras","text-data-wordbreak"]},transition:{requires:["node-style"]},"transition-timer":{condition:{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"},requires:["transition"]},uploader:{requires:["uploader-html5","uploader-flash"]},"uploader-deprecated":{requires:["event-custom","node","base","swf"]},"uploader-flash":{requires:["swf","widget","substitute","base","cssbutton","node","event-custom","file-flash","uploader-queue"]},"uploader-html5":{requires:["widget","node-event-simulate","substitute","file-html5","uploader-queue"]},"uploader-queue":{requires:["base"]},view:{requires:["base-build","node-event-delegate"]},"view-node-map":{requires:["view"]},widget:{use:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]},"widget-anim":{requires:["anim-base","plugin","widget"]},"widget-autohide":{requires:["base-build","event-key","event-outside","widget"]},"widget-base":{requires:["attribute","base-base","base-pluginhost","classnamemanager","event-focus","node-base","node-style"],skinnable:!0},"widget-base-ie":{condition:{name:"widget-base-ie",trigger:"widget-base",ua:"ie"},requires:["widget-base"]},"widget-buttons":{requires:["button-plugin","cssbutton","widget-stdmod"]},"widget-child":{requires:["base-build","widget"]},"widget-htmlparser":{requires:["widget-base"]},"widget-locale":{requires:["widget-base"]},"widget-modality":{requires:["base-build","event-outside","widget"],skinnable:!0},"widget-parent":{requires:["arraylist","base-build","widget"]},"widget-position":{requires:["base-build","node-screen","widget"]},"widget-position-align":{requires:["widget-position"]},"widget-position-constrain":{requires:["widget-position"]},"widget-skin":{requires:["widget-base"]},"widget-stack":{requires:["base-build","widget"],skinnable:!0},"widget-stdmod":{requires:["base-build","widget"]},"widget-uievents":{requires:["node-event-delegate","widget-base"]},yql:{requires:["jsonp","jsonp-url"]},"yql-nodejs":{condition:{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}},"yql-winjs":{condition:{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"}},yui:{},"yui-base":{},"yui-later":{requires:["yui-base"]},"yui-log":{requires:["yui-base"]},"yui-throttle":{requires:["yui-base"]}},YUI.Env[e.version].md5="a28e022ad022130f7a4fb4ac77a2f1df"},"3.7.3",{requires:["loader-base"]});
diff --git a/js/yui3/loader/loader-min.js b/js/yui3/loader/loader-min.js
new file mode 100644
index 000000000..0c129c0ae
--- /dev/null
+++ b/js/yui3/loader/loader-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("loader-base",function(e,t){YUI.Env[e.version]||function(){var t=e.version,n="/build/",r=t+n,i=e.Env.base,s="gallery-2012.10.10-19-59",o="2in3",u="4",a="2.9.0",f=i+"combo?",l={version:t,root:r,base:e.Env.base,comboBase:f,skin:{defaultSkin:"sam",base:"assets/skins/",path:"skin.css",after:["cssreset","cssfonts","cssgrids","cssbase","cssreset-context","cssfonts-context"]},groups:{},patterns:{}},c=l.groups,h=function(e,t,r){var s=o+"."+(e||u)+"/"+(t||a)+n,l=r&&r.base?r.base:i,h=r&&r.comboBase?r.comboBase:f;c.yui2.base=l+s,c.yui2.root=s,c.yui2.comboBase=h},p=function(e,t){var r=(e||s)+n,o=t&&t.base?t.base:i,u=t&&t.comboBase?t.comboBase:f;c.gallery.base=o+r,c.gallery.root=r,c.gallery.comboBase=u};c[t]={},c.gallery={ext:!1,combine:!0,comboBase:f,update:p,patterns:{"gallery-":{},"lang/gallery-":{},"gallerycss-":{type:"css"}}},c.yui2={combine:!0,ext:!1,comboBase:f,update:h,patterns:{"yui2-":{configFn:function(e){/-skin|reset|fonts|grids|base/.test(e.name)&&(e.type="css",e.path=e.path.replace(/\.js/,".css"),e.path=e.path.replace(/\/yui2-skin/,"/assets/skins/sam/yui2-skin"))}}}},p(),h(),YUI.Env[t]=l}();var n={},r=[],i=1024,s=YUI.Env,o=s._loaded,u="css",a="js",f="intl",l="sam",c=e.version,h="",p=e.Object,d=p.each,v=e.Array,m=s._loaderQueue,g=s[c],y="skin-",b=e.Lang,w=s.mods,E,S=function(e,t,n,r){var i=e+"/"+t;return r||(i+="-min"),i+="."+(n||u),i};YUI.Env._cssLoaded||(YUI.Env._cssLoaded={}),e.Env.meta=g,e.Loader=function(t){var n=this;t=t||{},E=g.md5,n.context=e,n.base=e.Env.meta.base+e.Env.meta.root,n.comboBase=e.Env.meta.comboBase,n.combine=t.base&&t.base.indexOf(n.comboBase.substr(0,20))>-1,n.comboSep="&",n.maxURLLength=i,n.ignoreRegistered=t.ignoreRegistered,n.root=e.Env.meta.root,n.timeout=0,n.forceMap={},n.allowRollup=!1,n.filters={},n.required={},n.patterns={},n.moduleInfo={},n.groups=e.merge(e.Env.meta.groups),n.skin=e.merge(e.Env.meta.skin),n.conditions={},n.config=t,n._internal=!0,n._populateCache(),n.loaded=o[c],n.async=!0,n._inspectPage(),n._internal=!1,n._config(t),n.forceMap=n.force?e.Array.hash(n.force):{},n.testresults=null,e.config.tests&&(n.testresults=e.config.tests),n.sorted=[],n.dirty=!0,n.inserted={},n.skipped={},n.tested={},n.ignoreRegistered&&n._resetModules()},e.Loader.prototype={_populateCache:function(){var t=this,n=g.modules,r=s._renderedMods,i;if(r&&!t.ignoreRegistered){for(i in r)r.hasOwnProperty(i)&&(t.moduleInfo[i]=e.merge(r[i]));r=s._conditions;for(i in r)r.hasOwnProperty(i)&&(t.conditions[i]=e.merge(r[i]))}else for(i in n)n.hasOwnProperty(i)&&t.addModule(n[i],i)},_resetModules:function(){var e=this,t,n,r,i,s;for(t in e.moduleInfo)if(e.moduleInfo.hasOwnProperty(t)){r=e.moduleInfo[t],i=r.name,s=YUI.Env.mods[i]?YUI.Env.mods[i].details:null,s&&(e.moduleInfo[i]._reset=!0,e.moduleInfo[i].requires=s.requires||[],e.moduleInfo[i].optional=s.optional||[],e.moduleInfo[i].supersedes=s.supercedes||[]);if(r.defaults)for(n in r.defaults)r.defaults.hasOwnProperty(n)&&r[n]&&(r[n]=r.defaults[n]);delete r.langCache,delete r.skinCache,r.skinnable&&e._addSkin(e.skin.defaultSkin,r.name)}},REGEX_CSS:/\.css(?:[?;].*)?$/i,FILTER_DEFS:{RAW:{searchExp:"-min\\.js",replaceStr:".js"},DEBUG:{searchExp:"-min\\.js",replaceStr:"-debug.js"},COVERAGE:{searchExp:"-min\\.js",replaceStr:"-coverage.js"}},_inspectPage:function(){var e=this,t,n,r,i,s;for(s in e.moduleInfo)e.moduleInfo.hasOwnProperty(s)&&(t=e.moduleInfo[s],t.type&&t.type===u&&e.isCSSLoaded(t.name)&&(e.loaded[s]=!0));for(s in w)w.hasOwnProperty(s)&&(t=w[s],t.details&&(n=e.moduleInfo[t.name],r=t.details.requires,i=n&&n.requires,n?!n._inspected&&r&&i.length!==r.length&&delete n.expanded:n=e.addModule(t.details,s),n._inspected=!0))},_requires:function(e,t){var n,r,i,s,o=this.moduleInfo,a=o[e],f=o[t];if(!a||!f)return!1;r=a.expanded_map,i=a.after_map;if(i&&t in i)return!0;i=f.after_map;if(i&&e in i)return!1;s=o[t]&&o[t].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(e,s[n]))return!0;s=o[e]&&o[e].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(t,s[n]))return!1;return r&&t in r?!0:a.ext&&a.type===u&&!f.ext&&f.type===u?!0:!1},_config:function(t){var n,r,i,s,o,u,a,f=this,l=[],c;if(t)for(n in t)if(t.hasOwnProperty(n)){i=t[n];if(n==="require")f.require(i);else if(n==="skin")typeof i=="string"&&(f.skin.defaultSkin=t.skin,i={defaultSkin:i}),e.mix(f.skin,i,!0);else if(n==="groups"){for(r in i)if(i.hasOwnProperty(r)){a=r,u=i[r],f.addGroup(u,a);if(u.aliases)for(s in u.aliases)u.aliases.hasOwnProperty(s)&&f.addAlias(u.aliases[s],s)}}else if(n==="modules")for(r in i)i.hasOwnProperty(r)&&f.addModule(i[r],r);else if(n==="aliases")for(r in i)i.hasOwnProperty(r)&&f.addAlias(i[r],r);else n==="gallery"?this.groups.gallery.update(i,t):n==="yui2"||n==="2in3"?this.groups.yui2.update(t["2in3"],t.yui2,t):f[n]=i}o=f.filter,b.isString(o)&&(o=o.toUpperCase(),f.filterName=o,f.filter=f.FILTER_DEFS[o],o==="DEBUG"&&f.require("yui-log","dump"));if(f.filterName&&f.coverage&&f.filterName==="COVERAGE"&&b.isArray(f.coverage)&&f.coverage.length){for(n=0;n<f.coverage.length;n++)c=f.coverage[n],f.moduleInfo[c]&&f.moduleInfo[c].use?l=[].concat(l,f.moduleInfo[c].use):l.push(c);f.filters=f.filters||{},e.Array.each(l,function(e){f.filters[e]=f.FILTER_DEFS.COVERAGE}),f.filterName="RAW",f.filter=f.FILTER_DEFS[f.filterName]}},formatSkin:function(e,t){var n=y+e;return t&&(n=n+"-"+t),n},_addSkin:function(e,t,n){var r,i,s,o,u=this.moduleInfo,a=this.skin,f=u[t]&&u[t].ext;return t&&(s=this.formatSkin(e,t),u[s]||(r=u[t],i=r.pkg||t,o={skin:!0,name:s,group:r.group,type:"css",after:a.after,path:(n||i)+"/"+a.base+e+"/"+t+".css",ext:f},r.base&&(o.base=r.base),r.configFn&&(o.configFn=r.configFn),this.addModule(o,s))),s},addAlias:function(e,t){YUI.Env.aliases[t]=e,this.addModule({name:t,use:e})},addGroup:function(e,t){var n=e.modules,r=this,i,s;t=t||e.name,e.name=t,r.groups[t]=e;if(e.patterns)for(i in e.patterns)e.patterns.hasOwnProperty(i)&&(e.patterns[i].group=t,r.patterns[i]=e.patterns[i]);if(n)for(i in n)n.hasOwnProperty(i)&&(s=n[i],typeof s=="string"&&(s={name:i,fullpath:s}),s.group=t,r.addModule(s,i))},addModule:function(t,n){n=n||t.name,typeof t=="string"&&(t={name:n,fullpath:t});var r,i,o,f,l,c,p,d,m,g,y,b,w,E,x,T,N,C,k,L,A,O,M=this.conditions,_;this.moduleInfo[n]&&this.moduleInfo[n].temp&&(t=e.merge(this.moduleInfo[n],t)),t.name=n;if(!t||!t.name)return null;t.type||(t.type=a,O=t.path||t.fullpath,O&&this.REGEX_CSS.test(O)&&(t.type=u)),!t.path&&!t.fullpath&&(t.path=S(n,n,t.type)),t.supersedes=t.supersedes||t.use,t.ext="ext"in t?t.ext:this._internal?!1:!0,r=t.submodules,this.moduleInfo[n]=t,t.requires=t.requires||[];if(this.requires)for(i=0;i<this.requires.length;i++)t.requires.push(this.requires[i]);if(t.group&&this.groups&&this.groups[t.group]){A=this.groups[t.group];if(A.requires)for(i=0;i<A.requires.length;i++)t.requires.push(A.requires[i])}t.defaults||(t.defaults={requires:t.requires?[].concat(t.requires):null,supersedes:t.supersedes?[].concat(t.supersedes):null,optional:t.optional?[].concat(t.optional):null}),t.skinnable&&t.ext&&t.temp&&(k=this._addSkin(this.skin.defaultSkin,n),t.requires.unshift(k)),t.requires.length&&(t.requires=this.filterRequires(t.requires)||[]);if(!t.langPack&&t.lang){y=v(t.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b))}if(r){l=t.supersedes||[],o=0;for(i in r)if(r.hasOwnProperty(i)){c=r[i],c.path=c.path||S(n,i,t.type),c.pkg=n,c.group=t.group,c.supersedes&&(l=l.concat(c.supersedes)),p=this.addModule(c,i),l.push(i);if(p.skinnable){t.skinnable=!0,C=this.skin.overrides;if(C&&C[i])for(g=0;g<C[i].length;g++)k=this._addSkin(C[i][g],i,n),l.push(k);k=this._addSkin(this.skin.defaultSkin,i,n),l.push(k)}if(c.lang&&c.lang.length){y=v(c.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),w=this.getLangPackName(T,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),E=E||v.hash(p.supersedes),w in E||p.supersedes.push(w),t.lang=t.lang||[],x=x||v.hash(t.lang),T in x||t.lang.push(T),b=this.getLangPackName(h,n),w=this.getLangPackName(h,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),w in E||p.supersedes.push(w)}o++}t.supersedes=v.dedupe(l),this.allowRollup&&(t.rollup=o<4?o:Math.min(o-1,4))}d=t.plugins;if(d)for(i in d)d.hasOwnProperty(i)&&(m=d[i],m.pkg=n,m.path=m.path||S(n,i,t.type),m.requires=m.requires||[],m.group=t.group,this.addModule(m,i),t.skinnable&&this._addSkin(this.skin.defaultSkin,i,n));if(t.condition){f=t.condition.trigger,YUI.Env.aliases[f]&&(f=YUI.Env.aliases[f]),e.Lang.isArray(f)||(f=[f]);for(i=0;i<f.length;i++)_=f[i],L=t.condition.when,M[_]=M[_]||{},M[_][n]=t.condition,L&&L!=="after"?L==="instead"&&(t.supersedes=t.supersedes||[],t.supersedes.push(_)):(t.after=t.after||[],t.after.push(_))}return t.supersedes&&(t.supersedes=this.filterRequires(t.supersedes)),t.after&&(t.after=this.filterRequires(t.after),t.after_map=v.hash(t.after)),t.configFn&&(N=t.configFn(t),N===!1&&(delete this.moduleInfo[n],delete s._renderedMods[n],t=null)),t&&(s._renderedMods||(s._renderedMods={}),s._renderedMods[n]=e.mix(s._renderedMods[n]||{},t),s._conditions=M),t},require:function(t){var n=typeof t=="string"?v(arguments):t;this.dirty=!0,this.required=e.merge(this.required,v.hash(this.filterRequires(n))),this._explodeRollups()},_explodeRollups:function(){var e=this,t,n,r,i,s,o,u,a=e.required;if(!e.allowRollup){for(r in a)if(a.hasOwnProperty(r)){t=e.getModule(r);if(t&&t.use){o=t.use.length;for(i=0;i<o;i++){n=e.getModule(t.use[i]);if(n&&n.use){u=n.use.length;for(s=0;s<u;s++)a[n.use[s]]=!0}else a[t.use[i]]=!0}}}e.required=a}},filterRequires:function(t){if(t){e.Lang.isArray(t)||(t=[t]),t=e.Array(t);var n=[],r,i,s,o;for(r=0;r<t.length;r++){i=this.getModule(t[r]);if(i&&i.use)for(s=0;s<i.use.length;s++)o=this.getModule(i.use[s]),o&&o.use&&o.name!==i.name?n=e.Array.dedupe([].concat(n,this.filterRequires(o.use))):n.push(i.use[s]);else n.push(t[r])}t=n}return t},getRequires:function(t){if(!t)return r;if(t._parsed)return t.expanded||r;var n,i,s,o,u,a,l=this.testresults,c=t.name,m,g=w[c]&&w[c].details,y,b,E,S,x,T,N,C,k,L,A=t.lang||t.intl,O=this.moduleInfo,M=e.Features&&e.Features.tests.load,_,D;t.temp&&g&&(x=t,t=this.addModule(g,c),t.group=x.group,t.pkg=x.pkg,delete t.expanded),D=!!this.lang&&t.langCache!==this.lang||t.skinCache!==this.skin.defaultSkin;if(t.expanded&&!D)return t.expanded;y=[],_={},S=this.filterRequires(t.requires),t.lang&&(y.unshift("intl"),S.unshift("intl"),A=!0),T=this.filterRequires(t.optional),t._parsed=!0,t.langCache=this.lang,t.skinCache=this.skin.defaultSkin;for(n=0;n<S.length;n++)if(!_[S[n]]){y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}S=this.filterRequires(t.supersedes);if(S)for(n=0;n<S.length;n++)if(!_[S[n]]){t.submodules&&y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}if(T&&this.loadOptional)for(n=0;n<T.length;n++)if(!_[T[n]]){y.push(T[n]),_[T[n]]=!0,i=O[T[n]];if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}m=this.conditions[c];if(m){t._parsed=!1;if(l&&M)d(l,function(e,t){var n=M[t].name;!_[n]&&M[t].trigger===c&&e&&M[t]&&(_[n]=!0,y.push(n))});else for(n in m)if(m.hasOwnProperty(n)&&!_[n]){E=m[n],b=E&&(!E.ua&&!E.test||E.ua&&e.UA[E.ua]||E.test&&E.test(e,S));if(b){_[n]=!0,y.push(n),i=this.getModule(n);if(i){o=this.getRequires(i);for(s=0;s<o.length;s++)y.push(o[s])}}}}if(t.skinnable){C=this.skin.overrides;for(n in YUI.Env.aliases)YUI.Env.aliases.hasOwnProperty(n)&&e.Array.indexOf(YUI.Env.aliases[n],c)>-1&&(k=n);if(C&&(C[c]||k&&C[k])){L=c,C[k]&&(L=k);for(n=0;n<C[L].length;n++)N=this._addSkin(C[L][n],c),this.isCSSLoaded(N,this._boot)||y.push(N)}else N=this._addSkin(this.skin.defaultSkin,c),this.isCSSLoaded(N,this._boot)||y.push(N)}return t._parsed=!1,A&&(t.lang&&!t.langPack&&e.Intl&&(a=e.Intl.lookupBestLang(this.lang||h,t.lang),u=this.getLangPackName(a,c),u&&y.unshift(u)),y.unshift(f)),t.expanded_map=v.hash(y),t.expanded=p.keys(t.expanded_map),t.expanded},isCSSLoaded:function(t,n){if(!t||!YUI.Env.cssStampEl||!n&&this.ignoreRegistered)return!1;var r=YUI.Env.cssStampEl,i=!1,s=YUI.Env._cssLoaded[t],o=r.currentStyle;return s!==undefined?s:(r.className=t,o||(o=e.config.doc.defaultView.getComputedStyle(r,null)),o&&o.display==="none"&&(i=!0),r.className="",YUI.Env._cssLoaded[t]=i,i)},getProvides:function(t){var r=this.getModule(t),i,s;return r?(r&&!r.provides&&(i={},s=r.supersedes,s&&v.each(s,function(t){e.mix(i,this.getProvides(t))},this),i[t]=!0,r.provides=i),r.provides):n},calculate:function(e,t){if(e||t||this.dirty)e&&this._config(e),this._init||this._setup(),this._explode(),this.allowRollup?this._rollup():this._explodeRollups(),this._reduce(),this._sort()},_addLangPack:function(t,n,r){var i=n.name,s,o,u=this.moduleInfo[r];return u||(s=S(n.pkg||i,r,a,!0),o={path:s,intl:!0,langPack:!0,ext:n.ext,group:n.group,supersedes:[]},n.root&&(o.root=n.root),n.base&&(o.base=n.base),n.configFn&&(o.configFn=n.configFn),this.addModule(o,r),t&&(e.Env.lang=e.Env.lang||{},e.Env.lang[t]=e.Env.lang[t]||{},e.Env.lang[t][i]=!0)),this.moduleInfo[r]},_setup:function(){var t=this.moduleInfo,n,r,i,o,u,a;for(n in t)t.hasOwnProperty(n)&&(o=t[n],o&&(o.requires=v.dedupe(o.requires),o.lang&&(a=this.getLangPackName(h,n),this._addLangPack(null,o,a))));u={},this.ignoreRegistered||e.mix(u,s.mods),this.ignore&&e.mix(u,v.hash(this.ignore));for(i in u)u.hasOwnProperty(i)&&e.mix(u,this.getProvides(i));if(this.force)for(r=0;r<this.force.length;r++)this.force[r]in u&&delete u[this.force[r]];e.mix(this.loaded,u),this._init=!0},getLangPackName:function(e,t){return"lang/"+t+(e?"_"+e:"")},_explode:function(){var t=this.required,n,r,i={},s=this,o,u;s.dirty=!1,s._explodeRollups(),t=s.required;for(o in t)t.hasOwnProperty(o)&&(i[o]||(i[o]=!0,n=s.getModule(o),n&&(u=n.expound,u&&(t[u]=s.getModule(u),r=s.getRequires(t[u]),e.mix(t,v.hash(r))),r=s.getRequires(n),e.mix(t,v.hash(r)))))},_patternTest:function(e,t){return e.indexOf(t)>-1},getModule:function(t){if(!t)return null;var n,r,i,s=this.moduleInfo[t],o=this.patterns;if(!s||s&&s.ext)for(i in o)if(o.hasOwnProperty(i)){n=o[i],n.test||(n.test=this._patternTest);if(n.test(t,i)){r=n;break}}return s?r&&s&&r.configFn&&!s.configFn&&(s.configFn=r.configFn,s.configFn(s)):r&&(n.action?n.action.call(this,t,i):(s=this.addModule(e.merge(r),t),r.configFn&&(s.configFn=r.configFn),s.temp=!0)),s},_rollup:function(){},_reduce:function(e){e=e||this.required;var t,n,r,i,s=this.loadType,o=this.ignore?v.hash(this.ignore):!1;for(t in e)if(e.hasOwnProperty(t)){i=this.getModule(t),((this.loaded[t]||w[t])&&!this.forceMap[t]&&!this.ignoreRegistered||s&&i&&i.type!==s)&&delete e[t],o&&o[t]&&delete e[t],r=i&&i.supersedes;if(r)for(n=0;n<r.length;n++)r[n]in e&&delete e[r[n]]}return e},_finish:function(e,t){m.running=!1;var n=this.onEnd;n&&n.call(this.context,{msg:e,data:this.data,success:t}),this._continue()},_onSuccess:function(){var t=this,n=e.merge(t.skipped),r,i=[],s=t.requireRegistration,o,u,f,l;for(f in n)n.hasOwnProperty(f)&&delete t.inserted[f];t.skipped={};for(f in t.inserted)t.inserted.hasOwnProperty(f)&&(l=t.getModule(f),!l||!s||l.type!==a||f in YUI.Env.mods?e.mix(t.loaded,t.getProvides(f)):i.push(f));r=t.onSuccess,u=i.length?"notregistered":"success",o=!i.length,r&&r.call(t.context,{msg:u,data:t.data,success:o,failed:i,skipped:n}),t._finish(u,o)},_onProgress:function(e){var t=this,n;if(e.data&&e.data.length)for(n=0;n<e.data.length;n++)e.data[n]=t.getModule(e.data[n].name);t.onProgress&&t.onProgress.call(t.context,{name:e.url,data:e.data})},_onFailure:function(e){var t=this.onFailure,n=[],r=0,i=e.errors.length;for(r;r<i;r++)n.push(e.errors[r].error);n=n.join(","),t&&t.call(this.context,{msg:n,data:this.data,success:!1}),this._finish(n,!1)},_onTimeout:function(){var e=this.onTimeout;e&&e.call(this.context,{msg:"timeout",data:this.data,success:!1})},_sort:function(){var e=p.keys(this.required),t={},n=0,r,i,s,o,u,a,f;for(;;){r=e.length,a=!1;for(o=n;o<r;o++){i=e[o];for(u=o+1;u<r;u++){f=i+e[u];if(!t[f]&&this._requires(i,e[u])){s=e.splice(u,1),e.splice(o,0,s[0]),t[f]=!0,a=!0;break}}if(a)break;n++}if(!a)break}this.sorted=e},_insert:function(t,n,r,i){t&&this._config(t);var s=this.resolve(!i),o=this,f=0,l=0,c={},h,p;o._refetch=[],r&&(s[r===a?u:a]=[]),o.fetchCSS||(s.css=[]),s.js.length&&f++,s.css.length&&f++,p=function(t){l++;var n={},r=0,i=0,s="",u,a,p;if(t&&t.errors)for(r=0;r<t.errors.length;r++)t.errors[r].request?s=t.errors[r].request.url:s=t.errors[r],n[s]=s;if(t&&t.data&&t.data.length&&t.type==="success")for(r=0;r<t.data.length;r++){o.inserted[t.data[r].name]=!0;if(t.data[r].lang||t.data[r].skinnable)delete o.inserted[t.data[r].name],o._refetch.push(t.data[r].name)}if(l===f){o._loading=null;if(o._refetch.length){for(r=0;r<o._refetch.length;r++){h=o.getRequires(o.getModule(o._refetch[r]));for(i=0;i<h.length;i++)o.inserted[h[i]]||(c[h[i]]=h[i])}c=e.Object.keys(c);if(c.length){o.require(c),p=o.resolve(!0);if(p.cssMods.length){for(r=0;r<p.cssMods.length;r++)a=p.cssMods[r].name,delete YUI.Env._cssLoaded[a],o.isCSSLoaded(a)&&(o.inserted[a]=!0,delete o.required[a]);o.sorted=[],o._sort()}t=null,o._insert()}}t&&t.fn&&(u=t.fn,delete t.fn,u.call(o,t))}},this._loading=!0;if(!s.js.length&&!s.css.length){l=-1,p({fn:o._onSuccess});return}s.css.length&&e.Get.css(s.css,{data:s.cssMods,attributes:o.cssAttributes,insertBefore:o.insertBefore,charset:o.charset,timeout:o.timeout,context:o,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}}),s.js.length&&e.Get.js(s.js,{data:s.jsMods,insertBefore:o.insertBefore,attributes:o.jsAttributes,charset:o.charset,timeout:o.timeout,autopurge:!1,context:o,async:o.async,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}})},_continue:function(){!m.running&&m.size()>0&&(m.running=!0,m.next()())},insert:function(t,n,r){var i=this,s=e.merge(this);delete s.require,delete s.dirty,m.add(function(){i._insert(s,t,n,r)}),this._continue()},loadNext:function(){return},_filter:function(e,t,n){var r=this.filter,i=t&&t in this.filters,s=i&&this.filters[t],o=n||(this.moduleInfo[t]?this.moduleInfo[t].group:null);return o&&this.groups[o]&&this.groups[o].filter&&(s=this.groups[o].filter,i=!0),e&&(i&&(r=b.isString(s)?this.FILTER_DEFS[s.toUpperCase()]||null:s),r&&(e=e.replace(new RegExp(r.searchExp,"g"),r.replaceStr))),e},_url:function(e,t,n){return this._filter((n||this.base||"")+e,t)},resolve:function(e,t){var r,s,o,f,c,h,p,d,v,m,g,y,w,E,S=[],x,T,N={},C=this,k,A,O=C.ignoreRegistered?{}:C.inserted,M={js:[],jsMods:[],css:[],cssMods:[]},_=C.loadType||"js",D;(C.skin.overrides||C.skin.defaultSkin!==l||C.ignoreRegistered)&&C._resetModules(),e&&C.calculate(),t=t||C.sorted,D=function(e){if(e){c=e.group&&C.groups[e.group]||n,c.async===!1&&(e.async=c.async),f=e.fullpath?C._filter(e.fullpath,t[s]):C._url(e.path,t[s],c.base||e.base);if(e.attributes||e.async===!1)f={url:f,async:e.async},e.attributes&&(f.attributes=e.attributes);M[e.type].push(f),M[e.type+"Mods"].push(e)}},r=t.length,y=C.comboBase,f=y,m={};for(s=0;s<r;s++){v=y,o=C.getModule(t[s]),h=o&&o.group,c=C.groups[h];if(h&&c){if(!c.combine||o.fullpath){D(o);continue}o.combine=!0,c.comboBase&&(v=c.comboBase),"root"in c&&b.isValue(c.root)&&(o.root=c.root),o.comboSep=c.comboSep||C.comboSep,o.maxURLLength=c.maxURLLength||C.maxURLLength}else if(!C.combine){D(o);continue}m[v]=m[v]||[],m[v].push(o)}for(p in m)if(m.hasOwnProperty(p)){N[p]=N[p]||{js:[],jsMods:[],css:[],cssMods:[]},f=p,g=m[p],r=g.length;if(r)for(s=0;s<r;s++){if(O[g[s]])continue;o=g[s],o&&(o.combine||!o.ext)?(N[p].comboSep=o.comboSep,N[p].group=o.group,N[p].maxURLLength=o.maxURLLength,d=(b.isValue(o.root)?o.root:C.root)+(o.path||o.fullpath),d=C._filter(d,o.name),N[p][o.type].push(d),N[p][o.type+"Mods"].push(o)):g[s]&&D(g[s])}}for(p in N){w=p,k=N[w].comboSep||C.comboSep,A=N[w].maxURLLength||C.maxURLLength;for(_ in N[w])if(_===a||_===u){E=N[w][_],g=N[w][_+"Mods"],r=E.length,x=w+E.join(k),T=x.length,A<=w.length&&(A=i);if(r)if(T>A){S=[];for(t=0;t<r;t++)S.push(E[t]),x=w+S.join(k),x.length>A&&(o=S.pop(),x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)),S=[],o&&S.push(o));S.length&&(x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)))}else M[_].push(C._filter(x,null,N[w].group));M[_+"Mods"]=M[_+"Mods"].concat(g)}}return N=null,M},load:function(e){if(!e)return;var t=this,n=t.resolve(!0);t.data=n,t.onEnd=function(){e.apply(t.context||t,arguments)},t.insert()}}},"3.7.3",{requires:["get","features"]}),YUI.add("loader-rollup",function(e,t){e.Loader.prototype._rollup=function(){var e,t,n,r,i=this.required,s,o=this.moduleInfo,u,a,f;if(this.dirty||!this.rollups){this.rollups={};for(e in o)o.hasOwnProperty(e)&&(n=this.getModule(e),n&&n.rollup&&(this.rollups[e]=n))}for(;;){u=!1;for(e in this.rollups)if(this.rollups.hasOwnProperty(e)&&!i[e]&&(!this.loaded[e]||this.forceMap[e])){n=this.getModule(e),r=n.supersedes||[],s=!1;if(!n.rollup)continue;a=0;for(t=0;t<r.length;t++){f=o[r[t]];if(this.loaded[r[t]]&&!this.forceMap[r[t]]){s=!1;break}if(i[r[t]]&&n.type===f.type){a++,s=a>=n.rollup;if(s)break}}s&&(i[e]=!0,u=!0,this.getRequires(n))}if(!u)break}}},"3.7.3",{requires:["loader-base"]}),YUI.add("loader-yui3",function(e,t){YUI.Env[e.version].modules=YUI.Env[e.version].modules||{"align-plugin":{requires:["node-screen","node-pluginhost"]},anim:{use:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"]},"anim-base":{requires:["base-base","node-style"]},"anim-color":{requires:["anim-base"]},"anim-curve":{requires:["anim-xy"]},"anim-easing":{requires:["anim-base"]},"anim-node-plugin":{requires:["node-pluginhost","anim-base"]},"anim-scroll":{requires:["anim-base"]},"anim-shape":{requires:["anim-base","anim-easing","anim-color","matrix"]},"anim-shape-transform":{use:["anim-shape"]},"anim-xy":{requires:["anim-base","node-screen"]},app:{use:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"]},"app-base":{requires:["classnamemanager","pjax-base","router","view"]},"app-content":{requires:["app-base","pjax-content"]},"app-transitions":{requires:["app-base"]},"app-transitions-css":{type:"css"},"app-transitions-native":{condition:{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"},requires:["app-transitions","app-transitions-css","parallel","transition"]},"array-extras":{requires:["yui-base"]},"array-invoke":{requires:["yui-base"]},arraylist:{requires:["yui-base"]},"arraylist-add":{requires:["arraylist"]},"arraylist-filter":{requires:["arraylist"]},arraysort:{requires:["yui-base"]},"async-queue":{requires:["event-custom"]},attribute:{use:["attribute-base","attribute-complex"]},"attribute-base":{requires:["attribute-core","attribute-events","attribute-extras"]},"attribute-complex":{requires:["attribute-base"]},"attribute-core":{requires:["oop"]},"attribute-events":{requires:["event-custom"]},"attribute-extras":{requires:["oop"]},autocomplete:{use:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"]},"autocomplete-base":{optional:["autocomplete-sources"],requires:["array-extras","base-build","escape","event-valuechange","node-base"]},"autocomplete-filters":{requires:["array-extras","text-wordbreak"]},"autocomplete-filters-accentfold":{requires:["array-extras","text-accentfold","text-wordbreak"]},"autocomplete-highlighters":{requires:["array-extras","highlight-base"]},"autocomplete-highlighters-accentfold":{requires:["array-extras","highlight-accentfold"]},"autocomplete-list":{after:["autocomplete-sources"],lang:["en"],requires:["autocomplete-base","event-resize","node-screen","selector-css3","shim-plugin","widget","widget-position","widget-position-align"],skinnable:!0},"autocomplete-list-keys":{condition:{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"},requires:["autocomplete-list","base-build"]},"autocomplete-plugin":{requires:["autocomplete-list","node-pluginhost"]},"autocomplete-sources":{optional:["io-base","json-parse","jsonp","yql"],requires:["autocomplete-base"]},base:{use:["base-base","base-pluginhost","base-build"]},"base-base":{after:["attribute-complex"],requires:["base-core","attribute-base"]},"base-build":{requires:["base-base"]},"base-core":{requires:["attribute-core"]},"base-pluginhost":{requires:["base-base","pluginhost"]},button:{requires:["button-core","cssbutton","widget"]},"button-core":{requires:["attribute-core","classnamemanager","node-base"]},"button-group":{requires:["button-plugin","cssbutton","widget"]},"button-plugin":{requires:["button-core","cssbutton","node-pluginhost"]},cache:{use:["cache-base","cache-offline","cache-plugin"]},"cache-base":{requires:["base"]},"cache-offline":{requires:["cache-base","json"]},"cache-plugin":{requires:["plugin","cache-base"]},calendar:{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["calendar-base","calendarnavigator"],skinnable:!0},"calendar-base":{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["widget","substitute","datatype-date","datatype-date-math","cssgrids"],skinnable:!0},calendarnavigator:{requires:["plugin","classnamemanager","datatype-date","node","substitute"],skinnable:!0},charts:{requires:["charts-base"]},"charts-base":{requires:["dom","datatype-number","datatype-date","event-custom","event-mouseenter","event-touch","widget","widget-position","widget-stack","graphics"]},"charts-legend":{requires:["charts-base"]},classnamemanager:{requires:["yui-base"]},"clickable-rail":{requires:["slider-base"]},collection:{use:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"]},console:{lang:["en","es","ja"],requires:["yui-log","widget"],skinnable:!0},"console-filters":{requires:["plugin","console"],skinnable:!0},controller:{use:["router"]},cookie:{requires:["yui-base"]},"createlink-base":{requires:["editor-base"]},cssbase:{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},"cssbase-context":{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},cssbutton:{type:"css"},cssfonts:{type:"css"},"cssfonts-context":{type:"css"},cssgrids:{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-base":{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-units":{optional:["cssreset","cssfonts"],requires:["cssgrids-base"],type:"css"},cssreset:{type:"css"},"cssreset-context":{type:"css"},dataschema:{use:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"]},"dataschema-array":{requires:["dataschema-base"]},"dataschema-base":{requires:["base"]},"dataschema-json":{requires:["dataschema-base","json"]},"dataschema-text":{requires:["dataschema-base"]},"dataschema-xml":{requires:["dataschema-base"]},datasource:{use:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"]},"datasource-arrayschema":{requires:["datasource-local","plugin","dataschema-array"]},"datasource-cache":{requires:["datasource-local","plugin","cache-base"]},"datasource-function":{requires:["datasource-local"]},"datasource-get":{requires:["datasource-local","get"]},"datasource-io":{requires:["datasource-local","io-base"]},"datasource-jsonschema":{requires:["datasource-local","plugin","dataschema-json"]},"datasource-local":{requires:["base"]},"datasource-polling":{requires:["datasource-local"]},"datasource-textschema":{requires:["datasource-local","plugin","dataschema-text"]},"datasource-xmlschema":{requires:["datasource-local","plugin","datatype-xml","dataschema-xml"]},datatable:{use:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"]},"datatable-base":{requires:["datatable-core","datatable-table","datatable-head","datatable-body","base-build","widget"],skinnable:!0},"datatable-base-deprecated":{requires:["recordset-base","widget","substitute","event-mouseenter"],skinnable:!0},"datatable-body":{requires:["datatable-core","view","classnamemanager"]},"datatable-column-widths":{requires:["datatable-base"]},"datatable-core":{requires:["escape","model-list","node-event-delegate"]},"datatable-datasource":{requires:["datatable-base","plugin","datasource-local"]},"datatable-datasource-deprecated":{requires:["datatable-base-deprecated","plugin","datasource-local"]},"datatable-deprecated":{use:["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"]},"datatable-head":{requires:["datatable-core","view","classnamemanager"]},"datatable-message":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-mutable":{requires:["datatable-base"]},"datatable-scroll":{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0},"datatable-scroll-deprecated":{requires:["datatable-base-deprecated","plugin"]},"datatable-sort":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-sort-deprecated":{lang:["en"],requires:["datatable-base-deprecated","plugin","recordset-sort"]},"datatable-table":{requires:["datatable-core","datatable-head","datatable-body","view","classnamemanager"]},datatype:{use:["datatype-date","datatype-number","datatype-xml"]},"datatype-date":{use:["datatype-date-parse","datatype-date-format","datatype-date-math"]},"datatype-date-format":{lang:["ar","ar-JO","ca","ca-ES","da","da-DK","de","de-AT","de-DE","el","el-GR","en","en-AU","en-CA","en-GB","en-IE","en-IN","en-JO","en-MY","en-NZ","en-PH","en-SG","en-US","es","es-AR","es-BO","es-CL","es-CO","es-EC","es-ES","es-MX","es-PE","es-PY","es-US","es-UY","es-VE","fi","fi-FI","fr","fr-BE","fr-CA","fr-FR","hi","hi-IN","id","id-ID","it","it-IT","ja","ja-JP","ko","ko-KR","ms","ms-MY","nb","nb-NO","nl","nl-BE","nl-NL","pl","pl-PL","pt","pt-BR","ro","ro-RO","ru","ru-RU","sv","sv-SE","th","th-TH","tr","tr-TR","vi","vi-VN","zh-Hans","zh-Hans-CN","zh-Hant","zh-Hant-HK","zh-Hant-TW"]},"datatype-date-math":{requires:["yui-base"]},"datatype-date-parse":{},"datatype-number":{use:["datatype-number-parse","datatype-number-format"]},"datatype-number-format":{},"datatype-number-parse":{},"datatype-xml":{use:["datatype-xml-parse","datatype-xml-format"]},"datatype-xml-format":{},"datatype-xml-parse":{},dd:{use:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"]},"dd-constrain":{requires:["dd-drag"]},"dd-ddm":{requires:["dd-ddm-base","event-resize"]},"dd-ddm-base":{requires:["node","base","yui-throttle","classnamemanager"]},"dd-ddm-drop":{requires:["dd-ddm"]},"dd-delegate":{requires:["dd-drag","dd-drop-plugin","event-mouseenter"]},"dd-drag":{requires:["dd-ddm-base"]},"dd-drop":{requires:["dd-drag","dd-ddm-drop"]},"dd-drop-plugin":{requires:["dd-drop"]},"dd-gestures":{condition:{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"},requires:["dd-drag","event-synthetic","event-gestures"]},"dd-plugin":{optional:["dd-constrain","dd-proxy"],requires:["dd-drag"]},"dd-proxy":{requires:["dd-drag"]},"dd-scroll":{requires:["dd-drag"]},dial:{lang:["en","es"],requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],skinnable:!0},dom:{use:["dom-base","dom-screen","dom-style","selector-native","selector"]},"dom-base":{requires:["dom-core"]},"dom-core":{requires:["oop","features"]},"dom-deprecated":{requires:["dom-base"]},"dom-screen":{requires:["dom-base","dom-style"]},"dom-style":{requires:["dom-base"]},"dom-style-ie":{condition:{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"},requires:["dom-style"]},dump:{requires:["yui-base"]},editor:{use:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"]},"editor-base":{requires:["base","frame","node","exec-command","editor-selection"]},"editor-bidi":{requires:["editor-base"]},"editor-br":{requires:["editor-base"]},"editor-lists":{requires:["editor-base"]},"editor-para":{requires:["editor-para-base"]},"editor-para-base":{requires:["editor-base"]},"editor-para-ie":{condition:{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"},requires:["editor-para-base"]},"editor-selection":{requires:["node"]},"editor-tab":{requires:["editor-base"]},escape:{requires:["yui-base"]},event:{after:["node-base"],use:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"]},"event-base":{after:["node-base"],requires:["event-custom-base"]},"event-base-ie":{after:["event-base"],condition:{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"},requires:["node-base"]},"event-contextmenu":{requires:["event-synthetic","dom-screen"]},"event-custom":{use:["event-custom-base","event-custom-complex"]},"event-custom-base":{requires:["oop"]},"event-custom-complex":{requires:["event-custom-base"]},"event-delegate":{requires:["node-base"]},"event-flick":{requires:["node-base","event-touch","event-synthetic"]},"event-focus":{requires:["event-synthetic"]},"event-gestures":{use:["event-flick","event-move"]},"event-hover":{requires:["event-mouseenter"]},"event-key":{requires:["event-synthetic"]},"event-mouseenter":{requires:["event-synthetic"]},"event-mousewheel":{requires:["node-base"]},"event-move":{requires:["node-base","event-touch","event-synthetic"]},"event-outside":{requires:["event-synthetic"]},"event-resize":{requires:["node-base","event-synthetic"]},"event-simulate":{requires:["event-base"]},"event-synthetic":{requires:["node-base","event-custom-complex"]},"event-tap":{requires:["node-base","event-base","event-touch","event-synthetic"]},"event-touch":{requires:["node-base"]},"event-valuechange":{requires:["event-focus","event-synthetic"]},"exec-command":{requires:["frame"]},features:{requires:["yui-base"]},file:{requires:["file-flash","file-html5"]},"file-flash":{requires:["base"]},"file-html5":{requires:["base"]},frame:{requires:["base","node","selector-css3","yui-throttle"]},"gesture-simulate":{requires:["async-queue","event-simulate","node-screen"]},get:{requires:["yui-base"]},graphics:{requires:["node","event-custom","pluginhost","matrix","classnamemanager"]},"graphics-canvas":{condition:{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"},requires:["graphics"]},"graphics-canvas-default":{condition:{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}},"graphics-svg":{condition:{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"},requires:["graphics"]},"graphics-svg-default":{condition:{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}},"graphics-vml":{condition:{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"},requires:["graphics"]},"graphics-vml-default":{condition:{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}},handlebars:{use:["handlebars-compiler"]},"handlebars-base":{requires:["escape"]},"handlebars-compiler":{requires:["handlebars-base"]},highlight:{use:["highlight-base","highlight-accentfold"]},"highlight-accentfold":{requires:["highlight-base","text-accentfold"]},"highlight-base":{requires:["array-extras","classnamemanager","escape","text-wordbreak"]},history:{use:["history-base","history-hash","history-hash-ie","history-html5"]},"history-base":{requires:["event-custom-complex"]},"history-hash":{after:["history-html5"],requires:["event-synthetic","history-base","yui-later"]},"history-hash-ie":{condition:{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"},requires:["history-hash","node-base"]},"history-html5":{optional:["json"],requires:["event-base","history-base","node-base"]},imageloader:{requires:["base-base","node-style","node-screen"]},intl:{requires:["intl-base","event-custom"]},"intl-base":{requires:["yui-base"]},io:{use:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"]},"io-base":{requires:["event-custom-base","querystring-stringify-simple"]},"io-form":{requires:["io-base","node-base"]},"io-nodejs":{condition:{name:"io-nodejs",trigger:"io-base",ua:"nodejs"},requires:["io-base"]},"io-queue":{requires:["io-base","queue-promote"]},"io-upload-iframe":{requires:["io-base","node-base"]},"io-xdr":{requires:["io-base","datatype-xml-parse"]},json:{use:["json-parse","json-stringify"]},"json-parse":{requires:["yui-base"]},"json-stringify":{requires:["yui-base"]},jsonp:{requires:["get","oop"]},"jsonp-url":{requires:["jsonp"]},"lazy-model-list":{requires:["model-list"]},loader:{use:["loader-base","loader-rollup","loader-yui3"]},"loader-base":{requires:["get","features"]},"loader-rollup":{requires:["loader-base"]},"loader-yui3":{requires:["loader-base"]},matrix:{requires:["yui-base"]},model:{requires:["base-build","escape","json-parse"]},"model-list":{requires:["array-extras","array-invoke","arraylist","base-build","escape","json-parse","model"]},"model-sync-rest":{requires:["model","io-base","json-stringify"]},node:{use:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"]},"node-base":{requires:["event-base","node-core","dom-base"]},"node-core":{requires:["dom-core","selector"]},"node-deprecated":{requires:["node-base"]},"node-event-delegate":{requires:["node-base","event-delegate"]},"node-event-html5":{requires:["node-base"]},"node-event-simulate":{requires:["node-base","event-simulate","gesture-simulate"]},"node-flick":{requires:["classnamemanager","transition","event-flick","plugin"],skinnable:!0},"node-focusmanager":{requires:["attribute","node","plugin","node-event-simulate","event-key","event-focus"]},"node-load":{requires:["node-base","io-base"]},"node-menunav":{requires:["node","classnamemanager","plugin","node-focusmanager"],skinnable:!0},"node-pluginhost":{requires:["node-base","pluginhost"]},"node-screen":{requires:["dom-screen","node-base"]},"node-scroll-info":{requires:["base-build","dom-screen","event-resize","node-pluginhost","plugin"]},"node-style":{requires:["dom-style","node-base"]},oop:{requires:["yui-base"]},overlay:{requires:["widget","widget-stdmod","widget-position","widget-position-align","widget-stack","widget-position-constrain"],skinnable:!0},panel:{requires:["widget","widget-autohide","widget-buttons","widget-modality","widget-position","widget-position-align","widget-position-constrain","widget-stack","widget-stdmod"],skinnable:!0},parallel:{requires:["yui-base"]},pjax:{requires:["pjax-base","pjax-content"]},"pjax-base":{requires:["classnamemanager","node-event-delegate","router"]},"pjax-content":{requires:["io-base","node-base","router"]},"pjax-plugin":{requires:["node-pluginhost","pjax","plugin"]},plugin:{requires:["base-base"]},pluginhost:{use:["pluginhost-base","pluginhost-config"]},"pluginhost-base":{requires:["yui-base"]},"pluginhost-config":{requires:["pluginhost-base"]},profiler:{requires:["yui-base"]},querystring:{use:["querystring-parse","querystring-stringify"]},"querystring-parse":{requires:["yui-base","array-extras"]},"querystring-parse-simple":{requires:["yui-base"]},"querystring-stringify":{requires:["yui-base"]},"querystring-stringify-simple":{requires:["yui-base"]},"queue-promote":{requires:["yui-base"]},"range-slider":{requires:["slider-base","slider-value-range","clickable-rail"]},recordset:{use:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"]},"recordset-base":{requires:["base","arraylist"]},"recordset-filter":{requires:["recordset-base","array-extras","plugin"]},"recordset-indexer":{requires:["recordset-base","plugin"]},"recordset-sort":{requires:["arraysort","recordset-base","plugin"]},resize:{use:["resize-base","resize-proxy","resize-constrain"]},"resize-base":{requires:["base","widget","event","oop","dd-drag","dd-delegate","dd-drop"],skinnable:!0},"resize-constrain":{requires:["plugin","resize-base"]},"resize-plugin":{optional:["resize-constrain"],requires:["resize-base","plugin"]},"resize-proxy":{requires:["plugin","resize-base"]},router:{optional:["querystring-parse"],requires:["array-extras","base-build","history"]},scrollview:{requires:["scrollview-base","scrollview-scrollbars"]},"scrollview-base":{requires:["widget","event-gestures","event-mousewheel","transition"],skinnable:!0},"scrollview-base-ie":{condition:{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"},requires:["scrollview-base"]},"scrollview-list":{requires:["plugin","classnamemanager"],skinnable:!0},"scrollview-paginator":{requires:["plugin","classnamemanager"]},"scrollview-scrollbars":{requires:["classnamemanager","transition","plugin"],skinnable:!0},selector:{requires:["selector-native"]},"selector-css2":{condition:{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"},requires:["selector-native"]},"selector-css3":{requires:["selector-native","selector-css2"]},"selector-native":{requires:["dom-base"]},"shim-plugin":{requires:["node-style","node-pluginhost"]},slider:{use:["slider-base","slider-value-range","clickable-rail","range-slider"]},"slider-base":{requires:["widget","dd-constrain","event-key"],skinnable:!0},"slider-value-range":{requires:["slider-base"]},sortable:{requires:["dd-delegate","dd-drop-plugin","dd-proxy"]},"sortable-scroll":{requires:["dd-scroll","sortable"]},stylesheet:{requires:["yui-base"]},substitute:{optional:["dump"],requires:["yui-base"]},swf:{requires:["event-custom","node","swfdetect","escape"]},swfdetect:{requires:["yui-base"]},tabview:{requires:["widget","widget-parent","widget-child","tabview-base","node-pluginhost","node-focusmanager"],skinnable:!0},"tabview-base":{requires:["node-event-delegate","classnamemanager","skin-sam-tabview"]},"tabview-plugin":{requires:["tabview-base"]},test:{requires:["event-simulate","event-custom","json-stringify"]},"test-console":{requires:["console-filters","test","array-extras"],skinnable:!0},text:{use:["text-accentfold","text-wordbreak"]},"text-accentfold":{requires:["array-extras","text-data-accentfold"]},"text-data-accentfold":{requires:["yui-base"]},"text-data-wordbreak":{requires:["yui-base"]},"text-wordbreak":{requires:["array-extras","text-data-wordbreak"]},transition:{requires:["node-style"]},"transition-timer":{condition:{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"},requires:["transition"]},uploader:{requires:["uploader-html5","uploader-flash"]},"uploader-deprecated":{requires:["event-custom","node","base","swf"]},"uploader-flash":{requires:["swf","widget","substitute","base","cssbutton","node","event-custom","file-flash","uploader-queue"]},"uploader-html5":{requires:["widget","node-event-simulate","substitute","file-html5","uploader-queue"]},"uploader-queue":{requires:["base"]},view:{requires:["base-build","node-event-delegate"]},"view-node-map":{requires:["view"]},widget:{use:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]},"widget-anim":{requires:["anim-base","plugin","widget"]},"widget-autohide":{requires:["base-build","event-key","event-outside","widget"]},"widget-base":{requires:["attribute","base-base","base-pluginhost","classnamemanager","event-focus","node-base","node-style"],skinnable:!0},"widget-base-ie":{condition:{name:"widget-base-ie",trigger:"widget-base",ua:"ie"},requires:["widget-base"]},"widget-buttons":{requires:["button-plugin","cssbutton","widget-stdmod"]},"widget-child":{requires:["base-build","widget"]},"widget-htmlparser":{requires:["widget-base"]},"widget-locale":{requires:["widget-base"]},"widget-modality":{requires:["base-build","event-outside","widget"],skinnable:!0},"widget-parent":{requires:["arraylist","base-build","widget"]},"widget-position":{requires:["base-build","node-screen","widget"]},"widget-position-align":{requires:["widget-position"]},"widget-position-constrain":{requires:["widget-position"]},"widget-skin":{requires:["widget-base"]},"widget-stack":{requires:["base-build","widget"],skinnable:!0},"widget-stdmod":{requires:["base-build","widget"]},"widget-uievents":{requires:["node-event-delegate","widget-base"]},yql:{requires:["jsonp","jsonp-url"]},"yql-nodejs":{condition:{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}},"yql-winjs":{condition:{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"}},yui:{},"yui-base":{},"yui-later":{requires:["yui-base"]},"yui-log":{requires:["yui-base"]},"yui-throttle":{requires:["yui-base"]}},YUI.Env[e.version].md5="a28e022ad022130f7a4fb4ac77a2f1df"},"3.7.3",{requires:["loader-base"]}),YUI.add("loader",function(e,t){},"3.7.3",{use:["loader-base","loader-rollup","loader-yui3"]});
diff --git a/js/yui3/matrix/matrix-min.js b/js/yui3/matrix/matrix-min.js
new file mode 100644
index 000000000..839083615
--- /dev/null
+++ b/js/yui3/matrix/matrix-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("matrix",function(e,t){var n={_rounder:1e5,_round:function(e){return e=Math.round(e*n._rounder)/n._rounder,e},rad2deg:function(e){var t=e*(180/Math.PI);return t},deg2rad:function(e){var t=e*(Math.PI/180);return t},angle2rad:function(e){return typeof e=="string"&&e.indexOf("rad")>-1?e=parseFloat(e):e=n.deg2rad(parseFloat(e)),e},convertTransformToArray:function(e){var t=[[e.a,e.c,e.dx],[e.b,e.d,e.dy],[0,0,1]];return t},getDeterminant:function(e){var t=0,r=e.length,i=0,s;if(r==2)return e[0][0]*e[1][1]-e[0][1]*e[1][0];for(;i<r;++i)s=e[i][0],i%2===0||i===0?t+=s*n.getDeterminant(n.getMinors(e,i,0)):t-=s*n.getDeterminant(n.getMinors(e,i,0));return t},inverse:function(e){var t=0,r=e.length,i=0,s,o,u=[],a=[];if(r===2)t=e[0][0]*e[1][1]-e[0][1]*e[1][0],o=[[e[1][1]*t,-e[1][0]*t],[-e[0][1]*t,e[0][0]*t]];else{t=n.getDeterminant(e);for(;i<r;++i){u[i]=[];for(s=0;s<r;++s)a=n.getMinors(e,s,i),u[i][s]=n.getDeterminant(a),(i+s)%2!==0&&i+s!==0&&(u[i][s]*=-1)}o=n.scalarMultiply(u,1/t)}return o},scalarMultiply:function(e,t){var r=0,i,s=e.length;for(;r<s;++r)for(i=0;i<s;++i)e[r][i]=n._round(e[r][i]*t);return e},transpose:function(e){var t=e.length,n=0,r=0,i=[];for(;n<t;++n){i[n]=[];for(r=0;r<t;++r)i[n].push(e[r][n])}return i},getMinors:function(e,t,n){var r=[],i=e.length,s=0,o,u;for(;s<i;++s)if(s!==t){u=[];for(o=0;o<i;++o)o!==n&&u.push(e[s][o]);r.push(u)}return r},sign:function(e){return e===0?1:e/Math.abs(e)},vectorMatrixProduct:function(e,t){var n,r,i=e.length,s=[],o;for(n=0;n<i;++n){o=0;for(r=0;r<i;++r)o+=e[n]*t[n][r];s[n]=o}return s},decompose:function(e){var t=parseFloat(e[0][0]),r=parseFloat(e[1][0]),i=parseFloat(e[0][1]),s=parseFloat(e[1][1]),o=parseFloat(e[0][2]),u=parseFloat(e[1][2]),a,f,l,c;return t*s-r*i===0?!1:(f=n._round(Math.sqrt(t*t+r*r)),t/=f,r/=f,c=n._round(t*i+r*s),i-=t*c,s-=r*c,l=n._round(Math.sqrt(i*i+s*s)),i/=l,s/=l,c/=l,c=n._round(n.rad2deg(Math.atan(c))),a=n._round(n.rad2deg(Math.atan2(e[1][0],e[0][0]))),[["translate",o,u],["rotate",a],["skewX",c],["scale",f,l]])},getTransformArray:function(e){var t=/\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,r=[],i,s,o,u=n.transformMethods;while(s=t.exec(e))u.hasOwnProperty(s[1])?(i=s[2].split(","),i.unshift(s[1]),r.push(i)):s[1]=="matrix"&&(i=s[2].split(","),o=n.decompose([[i[0],i[2],i[4]],[i[1],i[3],i[5]],[0,0,1]]),r.push(o[0]),r.push(o[1]),r.push(o[2]),r.push(o[3]));return r},getTransformFunctionArray:function(e){var t;switch(e){case"skew":t=[e,0,0];break;case"scale":t=[e,1,1];break;case"scaleX":t=[e,1];break;case"scaleY":t=[e,1];break;case"translate":t=[e,0,0];break;default:t=[e,0]}return t},compareTransformSequence:function(e,t){var n=0,r=e.length,i=t.length,s=r===i;if(s)for(;n<r;++n)if(e[n][0]!=t[n][0]){s=!1;break}return s},transformMethods:{rotate:"rotate",skew:"skew",skewX:"skewX",skewY:"skewY",translate:"translate",translateX:"translateX",translateY:"tranlsateY",scale:"scale",scaleX:"scaleX",scaleY:"scaleY"}};e.MatrixUtil=n;var r=function(e){this.init(e)};r.prototype={_rounder:1e5,multiply:function(e,t,n,r,i,s){var o=this,u=o.a*e+o.c*t,a=o.b*e+o.d*t,f=o.a*n+o.c*r,l=o.b*n+o.d*r,c=o.a*i+o.c*s+o.dx,h=o.b*i+o.d*s+o.dy;return o.a=this._round(u),o.b=this._round(a),o.c=this._round(f),o.d=this._round(l),o.dx=this._round(c),o.dy=this._round(h),this},applyCSSText:function(e){var t=/\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,n,r;e=e.replace(/matrix/g,"multiply");while(r=t.exec(e))typeof this[r[1]]=="function"&&(n=r[2].split(","),this[r[1]].apply(this,n))},getTransformArray:function(e){var t=/\s*([a-z]*)\(([\w,\.,\-,\s]*)\)/gi,n=[],r,i;e=e.replace(/matrix/g,"multiply");while(i=t.exec(e))typeof this[i[1]]=="function"&&(r=i[2].split(","),r.unshift(i[1]),n.push(r));return n},_defaults:{a:1,b:0,c:0,d:1,dx:0,dy:0},_round:function(e){return e=Math.round(e*this._rounder)/this._rounder,e},init:function(e){var t=this._defaults,n;e=e||{};for(n in t)t.hasOwnProperty(n)&&(this[n]=n in e?e[n]:t[n]);this._config=e},scale:function(e,t){return this.multiply(e,0,0,t,0,0),this},skew:function(e,t){return e=e||0,t=t||0,e!==undefined&&(e=Math.tan(this.angle2rad(e))),t!==undefined&&(t=Math.tan(this.angle2rad(t))),this.multiply(1,t,e,1,0,0),this},skewX:function(e){return this.skew(e),this},skewY:function(e){return this.skew(null,e),this},toCSSText:function(){var e=this,t="matrix("+e.a+","+e.b+","+e.c+","+e.d+","+e.dx+","+e.dy+")";return t},toFilterText:function(){var e=this,t="progid:DXImageTransform.Microsoft.Matrix(";return t+="M11="+e.a+","+"M21="+e.b+","+"M12="+e.c+","+"M22="+e.d+","+'sizingMethod="auto expand")',t+="",t},rad2deg:function(e){var t=e*(180/Math.PI);return t},deg2rad:function(e){var t=e*(Math.PI/180);return t},angle2rad:function(e){return typeof e=="string"&&e.indexOf("rad")>-1?e=parseFloat(e):e=this.deg2rad(parseFloat(e)),e},rotate:function(e,t,n){var r=this.angle2rad(e),i=Math.sin(r),s=Math.cos(r);return this.multiply(s,i,0-i,s,0,0),this},translate:function(e,t){return e=parseFloat(e)||0,t=parseFloat(t)||0,this.multiply(1,0,0,1,e,t),this},translateX:function(e){return this.translate(e),this},translateY:function(e){return this.translate(null,e),this},identity:function(){var e=this._config,t=this._defaults,n;for(n in e)n in t&&(this[n]=t[n]);return this},getMatrixArray:function(){var e=this,t=[[e.a,e.c,e.dx],[e.b,e.d,e.dy],[0,0,1]];return t},getContentRect:function(e,t,n,r){var i=isNaN(n)?0:n,s=isNaN(r)?0:r,o=i+e,u=s+t,a=this,f=a.a,l=a.b,c=a.c,h=a.d,p=a.dx,d=a.dy,v=f*i+c*s+p,m=l*i+h*s+d,g=f*o+c*s+p,y=l*o+h*s+d,b=f*i+c*u+p,w=l*i+h*u+d,E=f*o+c*u+p,S=l*o+h*u+d;return{left:Math.min(b,Math.min(v,Math.min(g,E))),right:Math.max(b,Math.max(v,Math.max(g,E))),top:Math.min(y,Math.min(S,Math.min(w,m))),bottom:Math.max(y,Math.max(S,Math.max(w,m)))}},getDeterminant:function(){return e.MatrixUtil.getDeterminant(this.getMatrixArray())},inverse:function(){return e.MatrixUtil.inverse(this.getMatrixArray())},transpose:function(){return e.MatrixUtil.transpose(this.getMatrixArray())},decompose:function(){return e.MatrixUtil.decompose(this.getMatrixArray())}},e.Matrix=r},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/model-list/model-list-min.js b/js/yui3/model-list/model-list-min.js
new file mode 100644
index 000000000..75eb03d89
--- /dev/null
+++ b/js/yui3/model-list/model-list-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("model-list",function(e,t){function c(){c.superclass.constructor.apply(this,arguments)}var n=e.Attribute.prototype,r=e.Lang,i=e.Array,s="add",o="create",u="error",a="load",f="remove",l="reset";e.ModelList=e.extend(c,e.Base,{model:e.Model,_isYUIModelList:!0,initializer:function(t){t||(t={});var n=this.model=t.model||this.model;typeof n=="string"&&(this.model=e.Object.getValue(e,n.split(".")),this.model||e.error("ModelList: Model class not found: "+n)),this.publish(s,{defaultFn:this._defAddFn}),this.publish(l,{defaultFn:this._defResetFn}),this.publish(f,{defaultFn:this._defRemoveFn}),this.after("*:idChange",this._afterIdChange),this._clear(),t.items&&this.add(t.items,{silent:!0})},destructor:function(){this._clear()},add:function(t,n){var s=t._isYUIModelList;return s||r.isArray(t)?i.map(s?t.toArray():t,function(t,r){var i=n||{};return"index"in i&&(i=e.merge(i,{index:i.index+r})),this._add(t,i)},this):this._add(t,n)},create:function(t,n,r){var i=this;return typeof n=="function"&&(r=n,n={}),n||(n={}),t._isYUIModel||(t=new this.model(t)),i.fire(o,e.merge(n,{model:t})),t.save(n,function(e){e||i.add(t,n),r&&r.apply(null,arguments)})},each:function(e,t){var n=this._items.concat(),r,i,s;for(r=0,s=n.length;r<s;r++)i=n[r],e.call(t||i,i,r,this);return this},filter:function(e,t){var n=[],r=this._items,i,s,o,u;typeof e=="function"&&(t=e,e={});for(i=0,o=r.length;i<o;++i)s=r[i],t.call(this,s,i,this)&&n.push(s);return e.asList?(u=new this.constructor({model:this.model}),n.length&&u.add(n,{silent:!0}),u):n},get:function(e){return this.attrAdded(e)?n.get.apply(this,arguments):this.invoke("get",e)},getAsHTML:function(t){return this.attrAdded(t)?e.Escape.html(n.get.apply(this,arguments)):this.invoke("getAsHTML",t)},getAsURL:function(e){return this.attrAdded(e)?encodeURIComponent(n.get.apply(this,arguments)):this.invoke("getAsURL",e)},getByClientId:function(e){return this._clientIdMap[e]||null},getById:function(e){return this._idMap[e]||null},invoke:function(e){var t=[this._items,e].concat(i(arguments,1,!0));return i.invoke.apply(i,t)},load:function(e,t){var n=this;return typeof e=="function"&&(t=e,e={}),e||(e={}),this.sync("read",e,function(r,i){var s={options:e,response:i},o;r?(s.error=r,s.src="load",n.fire(u,s)):(n._loadEvent||(n._loadEvent=n.publish(a,{preventable:!1})),o=s.parsed=n._parse(i),n.reset(o,e),n.fire(a,s)),t&&t.apply(null,arguments)}),this},map:function(e,t){return i.map(this._items,e,t)},parse:function(t){if(typeof t=="string")try{return e.JSON.parse(t)||[]}catch(n){return this.fire(u,{error:n,response:t,src:"parse"}),null}return t||[]},remove:function(e,t){var n=e._isYUIModelList;return n||r.isArray(e)?(e=i.map(n?e.toArray():e,function(e){return r.isNumber(e)?this.item(e):e},this),i.map(e,function(e){return this._remove(e,t)},this)):this._remove(e,t)},reset:function(t,n){t||(t=[]),n||(n={});var r=e.merge({src:"reset"},n);return t._isYUIModelList?t=t.toArray():t=i.map(t,function(e){return e._isYUIModel?e:new this.model(e)},this),r.models=t,n.silent?this._defResetFn(r):(this.comparator&&t.sort(e.bind(this._sort,this)),this.fire(l,r)),this},some:function(e,t){var n=this._items.concat(),r,i,s;for(r=0,s=n.length;r<s;r++){i=n[r];if(e.call(t||i,i,r,this))return!0}return!1},sort:function(t){if(!this.comparator)return this;var n=this._items.concat(),r;return t||(t={}),n.sort(e.bind(this._sort,this)),r=e.merge(t,{models:n,src:"sort"}),t.silent?this._defResetFn(r):this.fire(l,r),this},sync:function(){var e=i(arguments,0,!0).pop();typeof e=="function"&&e()},toArray:function(){return this._items.concat()},toJSON:function(){return this.map(function(e){return e.toJSON()})},_add:function(t,n){var i,o;n||(n={}),t._isYUIModel||(t=new this.model(t)),o=t.get("id");if(this._clientIdMap[t.get("clientId")]||r.isValue(o)&&this._idMap[o]){this.fire(u,{error:"Model is already in the list.",model:t,src:"add"});return}return i=e.merge(n,{index:"index"in n?n.index:this._findIndex(t),model:t}),n.silent?this._defAddFn(i):this.fire(s,i),t},_attachList:function(e){e.lists.push(this),e.addTarget(this)},_clear:function(){i.each(this._items,this._detachList,this),this._clientIdMap={},this._idMap={},this._items=[]},_compare:function(e,t){return e<t?-1:e>t?1:0},_detachList:function(e){var t=i.indexOf(e.lists,this);t>-1&&(e.lists.splice(t,1),e.removeTarget(this))},_findIndex:function(e){var t=this._items,n=t.length,r=0,i,s,o;if(!this.comparator||!n)return n;o=this.comparator(e);while(r<n)s=r+n>>1,i=t[s],this._compare(this.comparator(i),o)<0?r=s+1:n=s;return r},_parse:function(e){return this.parse(e)},_remove:function(t,n){var i,s;n||(n={}),r.isNumber(t)?(i=t,t=this.item(i)):i=this.indexOf(t);if(i===-1||!t){this.fire(u,{error:"Model is not in the list.",index:i,model:t,src:"remove"});return}return s=e.merge(n,{index:i,model:t}),n.silent?this._defRemoveFn(s):this.fire(f,s),t},_sort:function(e,t){return this._compare(this.comparator(e),this.comparator(t))},_afterIdChange:function(e){var t=e.newVal,n=e.prevVal,i=e.target;if(r.isValue(n)){if(this._idMap[n]!==i)return;delete this._idMap[n]}else if(this.indexOf(i)===-1)return;r.isValue(t)&&(this._idMap[t]=i)},_defAddFn:function(e){var t=e.model,n=t.get("id");this._clientIdMap[t.get("clientId")]=t,r.isValue(n)&&(this._idMap[n]=t),this._attachList(t),this._items.splice(e.index,0,t)},_defRemoveFn:function(e){var t=e.model,n=t.get("id");this._detachList(t),delete this._clientIdMap[t.get("clientId")],r.isValue(n)&&delete this._idMap[n],this._items.splice(e.index,1)},_defResetFn:function(e){if(e.src==="sort"){this._items=e.models.concat();return}this._clear(),e.models.length&&this.add(e.models,{silent:!0})}},{NAME:"modelList"}),e.augment(c,e.ArrayList)},"3.7.3",{requires:["array-extras","array-invoke","arraylist","base-build","escape","json-parse","model"]});
diff --git a/js/yui3/model-sync-rest/model-sync-rest-min.js b/js/yui3/model-sync-rest/model-sync-rest-min.js
new file mode 100644
index 000000000..a3da8b792
--- /dev/null
+++ b/js/yui3/model-sync-rest/model-sync-rest-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("model-sync-rest",function(e,t){function r(){}var n=e.Lang;r.CSRF_TOKEN=YUI.Env.CSRF_TOKEN,r.EMULATE_HTTP=!1,r.HTTP_HEADERS={Accept:"application/json","Content-Type":"application/json"},r.HTTP_METHODS={create:"POST",read:"GET",update:"PUT","delete":"DELETE"},r.HTTP_TIMEOUT=3e4,r._NON_ATTRS_CFG=["root","url"],r.prototype={root:"",url:"",initializer:function(e){e||(e={}),"root"in e&&(this.root=e.root||""),"url"in e&&(this.url=e.url||"")},getURL:function(t,n){var r=this.root,i=this.url;return this._isYUIModelList?i?this._substituteURL(i,e.merge(this.getAttrs(),n)):this.model.prototype.root:r&&(t==="create"||this.isNew())?r:i?this._substituteURL(i,e.merge(this.getAttrs(),n)):this._joinURL(this.getAsURL("id")||"")},parseIOResponse:function(e){return e.responseText},serialize:function(t){return e.JSON.stringify(this)},sync:function(t,n,i){n||(n={});var s=this.getURL(t,n),o=r.HTTP_METHODS[t],u=e.merge(r.HTTP_HEADERS,n.headers),a=n.timeout||r.HTTP_TIMEOUT,f=n.csrfToken||r.CSRF_TOKEN,l;o==="POST"||o==="PUT"?l=this.serialize(t):delete u["Content-Type"],r.EMULATE_HTTP&&(o==="PUT"||o==="DELETE")&&(u["X-HTTP-Method-Override"]=o,o="POST"),f&&(o==="POST"||o==="PUT"||o==="DELETE")&&(u["X-CSRF-Token"]=f),this._sendSyncIORequest({action:t,callback:i,entity:l,headers:u,method:o,timeout:a,url:s})},_joinURL:function(e){var t=this.root;return!t&&!e?"":(e.charAt(0)==="/"&&(e=e.substring(1)),t&&t.charAt(t.length-1)==="/"?t+e+"/":t+"/"+e)},_parse:function(e){return typeof this.parseIOResponse=="function"&&(e=this.parseIOResponse(e)),this.parse(e)},_sendSyncIORequest:function(t){return e.io(t.url,{arguments:{action:t.action,callback:t.callback,url:t.url},context:this,data:t.entity,headers:t.headers,method:t.method,timeout:t.timeout,on:{start:this._onSyncIOStart,failure:this._onSyncIOFailure,success:this._onSyncIOSuccess,end:this._onSyncIOEnd}})},_substituteURL:function(t,r){if(!t)return"";var i={};return e.Object.each(r,function(e,t){if(n.isString(e)||n.isNumber(e))i[t]=encodeURIComponent(e)}),n.sub(t,i)},_onSyncIOEnd:function(e,t){},_onSyncIOFailure:function(e,t,n){var r=n.callback;r&&r({code:t.status,msg:t.statusText},t)},_onSyncIOSuccess:function(e,t,n){var r=n.callback;r&&r(null,t)},_onSyncIOStart:function(e,t){}},e.namespace("ModelSync").REST=r},"3.7.3",{requires:["model","io-base","json-stringify"]});
diff --git a/js/yui3/model/model-min.js b/js/yui3/model/model-min.js
new file mode 100644
index 000000000..3967bec7c
--- /dev/null
+++ b/js/yui3/model/model-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("model",function(e,t){function l(){l.superclass.constructor.apply(this,arguments)}var n=YUI.namespace("Env.Model"),r=e.Lang,i=e.Array,s=e.Object,o="change",u="error",a="load",f="save";e.Model=e.extend(l,e.Base,{idAttribute:"id",_allowAdHocAttrs:!0,_isYUIModel:!0,initializer:function(e){this.changed={},this.lastChange={},this.lists=[]},destroy:function(e,t){var n=this;return typeof e=="function"&&(t=e,e=null),n.onceAfter("destroy",function(){function r(r){r||i.each(n.lists.concat(),function(t){t.remove(n,e)}),t&&t.apply(null,arguments)}e&&(e.remove||e["delete"])?n.sync("delete",e,r):r()}),l.superclass.destroy.call(n)},generateClientId:function(){return n.lastId||(n.lastId=0),this.constructor.NAME+"_"+(n.lastId+=1)},getAsHTML:function(t){var n=this.get(t);return e.Escape.html(r.isValue(n)?String(n):"")},getAsURL:function(e){var t=this.get(e);return encodeURIComponent(r.isValue(t)?String(t):"")},isModified:function(){return this.isNew()||!s.isEmpty(this.changed)},isNew:function(){return!r.isValue(this.get("id"))},load:function(e,t){var n=this;return typeof e=="function"&&(t=e,e={}),e||(e={}),n.sync("read",e,function(r,i){var s={options:e,response:i},o;r?(s.error=r,s.src="load",n.fire(u,s)):(n._loadEvent||(n._loadEvent=n.publish(a,{preventable:!1})),o=s.parsed=n._parse(i),n.setAttrs(o,e),n.changed={},n.fire(a,s)),t&&t.apply(null,arguments)}),n},parse:function(t){if(typeof t=="string")try{return e.JSON.parse(t)}catch(n){return this.fire(u,{error:n,response:t,src:"parse"}),null}return t},save:function(e,t){var n=this;return typeof e=="function"&&(t=e,e={}),e||(e={}),n._validate(n.toJSON(),function(r){if(r){t&&t.call(null,r);return}n.sync(n.isNew()?"create":"update",e,function(r,i){var s={options:e,response:i},o;r?(s.error=r,s.src="save",n.fire(u,s)):(n._saveEvent||(n._saveEvent=n.publish(f,{preventable:!1})),i&&(o=s.parsed=n._parse(i),n.setAttrs(o,e)),n.changed={},n.fire(f,s)),t&&t.apply(null,arguments)})}),n},set:function(e,t,n){var r={};return r[e]=t,this.setAttrs(r,n)},setAttrs:function(t,n){var r=this.idAttribute,i,u,a,f,l;n||(n={}),l=n._transaction={},r!=="id"&&(t=e.merge(t),s.owns(t,r)?t.id=t[r]:s.owns(t,"id")&&(t[r]=t.id));for(a in t)s.owns(t,a)&&this._setAttr(a,t[a],n);if(!s.isEmpty(l)){i=this.changed,f=this.lastChange={};for(a in l)s.owns(l,a)&&(u=l[a],i[a]=u.newVal,f[a]={newVal:u.newVal,prevVal:u.prevVal,src:u.src||null});n.silent||(this._changeEvent||(this._changeEvent=this.publish(o,{preventable:!1})),this.fire(o,e.merge(n,{changed:f})))}return this},sync:function(){var e=i(arguments,0,!0).pop();typeof e=="function"&&e()},toJSON:function(){var e=this.getAttrs();return delete e.clientId,delete e.destroyed,delete e.initialized,this.idAttribute!=="id"&&delete e.id,e},undo:function(e,t){var n=this.lastChange,r=this.idAttribute,o={},u;return e||(e=s.keys(n)),i.each(e,function(e){s.owns(n,e)&&(e=e===r?"id":e,u=!0,o[e]=n[e].prevVal)}),u?this.setAttrs(o,t):this},validate:function(e,t){t&&t()},addAttr:function(e,t,n){var i=this.idAttribute,s,o;return i&&e===i&&(s=this._isLazyAttr("id")||this._getAttrCfg("id"),o=t.value===t.defaultValue?null:t.value,r.isValue(o)||(o=s.value===s.defaultValue?null:s.value,r.isValue(o)||(o=r.isValue(t.defaultValue)?t.defaultValue:s.defaultValue)),t.value=o,s.value!==o&&(s.value=o,this._isLazyAttr("id")?this._state.add("id","lazy",s):this._state.add("id","value",o))),l.superclass.addAttr.apply(this,arguments)},_parse:function(e){return this.parse(e)},_validate:function(e,t){function i(i){if(r.isValue(i)){n.fire(u,{attributes:e,error:i,src:"validate"}),t(i);return}t()}var n=this;n.validate.length===1?i(n.validate(e,i)):n.validate(e,i)},_defAttrChangeFn:function(e){var t=e.attrName;this._setAttrVal(t,e.subAttrName,e.prevVal,e.newVal)?(e.newVal=this.get(t),e._transaction&&(e._transaction[t]=e)):e.stopImmediatePropagation()}},{NAME:"model",ATTRS:{clientId:{valueFn:"generateClientId",readOnly:!0},id:{value:null}}})},"3.7.3",{requires:["base-build","escape","json-parse"]});
diff --git a/js/yui3/node-base/node-base-min.js b/js/yui3/node-base/node-base-min.js
new file mode 100644
index 000000000..07c4d845d
--- /dev/null
+++ b/js/yui3/node-base/node-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-base",function(e,t){var n=["hasClass","addClass","removeClass","replaceClass","toggleClass"];e.Node.importMethod(e.DOM,n),e.NodeList.importMethod(e.Node.prototype,n);var r=e.Node,i=e.DOM;r.create=function(t,n){return n&&n._node&&(n=n._node),e.one(i.create(t,n))},e.mix(r.prototype,{create:r.create,insert:function(e,t){return this._insert(e,t),this},_insert:function(e,t){var n=this._node,r=null;return typeof t=="number"?t=this._node.childNodes[t]:t&&t._node&&(t=t._node),e&&typeof e!="string"&&(e=e._node||e._nodes||e),r=i.addHTML(n,e,t),r},prepend:function(e){return this.insert(e,0)},append:function(e){return this.insert(e,null)},appendChild:function(e){return r.scrubVal(this._insert(e))},insertBefore:function(t,n){return e.Node.scrubVal(this._insert(t,n))},appendTo:function(t){return e.one(t).append(this),this},setContent:function(e){return this._insert(e,"replace"),this},getContent:function(e){return this.get("innerHTML")}}),e.Node.prototype.setHTML=e.Node.prototype.setContent,e.Node.prototype.getHTML=e.Node.prototype.getContent,e.NodeList.importMethod(e.Node.prototype,["append","insert","appendChild","insertBefore","prepend","setContent","getContent","setHTML","getHTML"]);var r=e.Node,i=e.DOM;r.ATTRS={text:{getter:function(){return i.getText(this._node)},setter:function(e){return i.setText(this._node,e),e}},"for":{getter:function(){return i.getAttribute(this._node,"for")},setter:function(e){return i.setAttribute(this._node,"for",e),e}},options:{getter:function(){return this._node.getElementsByTagName("option")}},children:{getter:function(){var t=this._node,n=t.children,r,i,s;if(!n){r=t.childNodes,n=[];for(i=0,s=r.length;i<s;++i)r[i].tagName&&(n[n.length]=r[i])}return e.all(n)}},value:{getter:function(){return i.getValue(this._node)},setter:function(e){return i.setValue(this._node,e),e}}},e.Node.importMethod(e.DOM,["setAttribute","getAttribute"]);var r=e.Node,s=e.NodeList;r.DOM_EVENTS={abort:1,beforeunload:1,blur:1,change:1,click:1,close:1,command:1,contextmenu:1,dblclick:1,DOMMouseScroll:1,drag:1,dragstart:1,dragenter:1,dragover:1,dragleave:1,dragend:1,drop:1,error:1,focus:1,key:1,keydown:1,keypress:1,keyup:1,load:1,message:1,mousedown:1,mouseenter:1,mouseleave:1,mousemove:1,mousemultiwheel:1,mouseout:1,mouseover:1,mouseup:1,mousewheel:1,orientationchange:1,reset:1,resize:1,select:1,selectstart:1,submit:1,scroll:1,textInput:1,unload:1},e.mix(r.DOM_EVENTS,e.Env.evt.plugins),e.augment(r,e.EventTarget),e.mix(r.prototype,{purge:function(t,n){return e.Event.purgeElement(this._node,t,n),this}}),e.mix(e.NodeList.prototype,{_prepEvtArgs:function(t,n,r){var i=e.Array(arguments,0,!0);return i.length<2?i[2]=this._nodes:i.splice(2,0,this._nodes),i[3]=r||this,i},on:function(t,n,r){return e.on.apply(e,this._prepEvtArgs.apply(this,arguments))},once:function(t,n,r){return e.once.apply(e,this._prepEvtArgs.apply(this,arguments))},after:function(t,n,r){return e.after.apply(e,this._prepEvtArgs.apply(this,arguments))},onceAfter:function(t,n,r){return e.onceAfter.apply(e,this._prepEvtArgs.apply(this,arguments))}}),s.importMethod(e.Node.prototype,["detach","detachAll"]),e.mix(e.Node.ATTRS,{offsetHeight:{setter:function(t){return e.DOM.setHeight(this._node,t),t},getter:function(){return this._node.offsetHeight}},offsetWidth:{setter:function(t){return e.DOM.setWidth(this._node,t),t},getter:function(){return this._node.offsetWidth}}}),e.mix(e.Node.prototype,{sizeTo:function(t,n){var r;arguments.length<2&&(r=e.one(t),t=r.get("offsetWidth"),n=r.get("offsetHeight")),this.setAttrs({offsetWidth:t,offsetHeight:n})}});var r=e.Node;e.mix(r.prototype,{show:function(e){return e=arguments[arguments.length-1],this.toggleView(!0,e),this},_show:function(){this.setStyle("display","")},_isHidden:function(){return e.DOM.getStyle(this._node,"display")==="none"},toggleView:function(e,t){return this._toggleView.apply(this,arguments),this},_toggleView:function(e,t){return t=arguments[arguments.length-1],typeof e!="boolean"&&(e=this._isHidden()?1:0),e?this._show():this._hide(),typeof t=="function"&&t.call(this),this},hide:function(e){return e=arguments[arguments.length-1],this.toggleView(!1,e),this},_hide:function(){this.setStyle("display","none")}}),e.NodeList.importMethod(e.Node.prototype,["show","hide","toggleView"]),e.config.doc.documentElement.hasAttribute||(e.Node.prototype.hasAttribute=function(e){return e==="value"&&this.get("value")!==""?!0:!!this._node.attributes[e]&&!!this._node.attributes[e].specified}),e.Node.prototype.focus=function(){try{this._node.focus()}catch(e){}return this},e.Node.ATTRS.type={setter:function(e){if(e==="hidden")try{this._node.type="hidden"}catch(t){this.setStyle("display","none"),this._inputType="hidden"}else try{this._node.type=e}catch(t){}return e},getter:function(){return this._inputType||this._node.type},_bypassProxy:!0},e.config.doc.createElement("form").elements.nodeType&&(e.Node.ATTRS.elements={getter:function(){return this.all("input, textarea, button, select")}}),e.mix(e.Node.prototype,{_initData:function(){"_data"in this||(this._data={})},getData:function(t){this._initData();var n=this._data,r=n;return arguments.length?t in n?r=n[t]:r=this._getDataAttribute(t):typeof n=="object"&&n!==null&&(r={},e.Object.each(n,function(e,t){r[t]=e}),r=this._getDataAttributes(r)),r},_getDataAttributes:function(e){e=e||{};var t=0,n=this._node.attributes,r=n.length,i=this.DATA_PREFIX,s=i.length,o;while(t<r)o=n[t].name,o.indexOf(i)===0&&(o=o.substr(s),o in e||(e[o]=this._getDataAttribute(o))),t+=1;return e},_getDataAttribute:function(e){var e=this.DATA_PREFIX+e,t=this._node,n=t.attributes,r=n&&n[e]&&n[e].value;return r},setData:function(e,t){return this._initData(),arguments.length>1?this._data[e]=t:this._data=e,this},clearData:function(e){return"_data"in this&&(typeof e!="undefined"?delete this._data[e]:delete this._data),this}}),e.mix(e.NodeList.prototype,{getData:function(e){var t=arguments.length?[e]:[];return this._invoke("getData",t,!0)},setData:function(e,t){var n=arguments.length>1?[e,t]:[e];return this._invoke("setData",n)},clearData:function(e){var t=arguments.length?[e]:[];return this._invoke("clearData",[e])}})},"3.7.3",{requires:["event-base","node-core","dom-base"]});
diff --git a/js/yui3/node-core/node-core-min.js b/js/yui3/node-core/node-core-min.js
new file mode 100644
index 000000000..ad613e8a7
--- /dev/null
+++ b/js/yui3/node-core/node-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-core",function(e,t){var n=".",r="nodeName",i="nodeType",s="ownerDocument",o="tagName",u="_yuid",a={},f=Array.prototype.slice,l=e.DOM,c=function(t){if(!this.getDOMNode)return new c(t);if(typeof t=="string"){t=c._fromString(t);if(!t)return null}var n=t.nodeType!==9?t.uniqueID:t[u];n&&c._instances[n]&&c._instances[n]._node!==t&&(t[u]=null),n=n||e.stamp(t),n||(n=e.guid()),this[u]=n,this._node=t,this._stateProxy=t,this._initPlugins&&this._initPlugins()},h=function(t){var n=null;return t&&(n=typeof t=="string"?function(n){return e.Selector.test(n,t)}:function(n){return t(e.one(n))}),n};c.ATTRS={},c.DOM_EVENTS={},c._fromString=function(t){return t&&(t.indexOf("doc")===0?t=e.config.doc:t.indexOf("win")===0?t=e.config.win:t=e.Selector.query(t,null,!0)),t||null},c.NAME="node",c.re_aria=/^(?:role$|aria-)/,c.SHOW_TRANSITION="fadeIn",c.HIDE_TRANSITION="fadeOut",c._instances={},c.getDOMNode=function(e){return e?e.nodeType?e:e._node||null:null},c.scrubVal=function(t,n){if(t){if(typeof t=="object"||typeof t=="function")if(i in t||l.isWindow(t))t=e.one(t);else if(t.item&&!t._nodes||t[0]&&t[0][i])t=e.all(t)}else typeof t=="undefined"?t=n:t===null&&(t=null);return t},c.addMethod=function(e,t,n){e&&t&&typeof t=="function"&&(c.prototype[e]=function(){var e=f.call(arguments),n=this,r;return e[0]&&e[0]._node&&(e[0]=e[0]._node),e[1]&&e[1]._node&&(e[1]=e[1]._node),e.unshift(n._node),r=t.apply(n,e),r&&(r=c.scrubVal(r,n)),typeof r!="undefined"||(r=n),r})},c.importMethod=function(t,n,r){typeof n=="string"?(r=r||n,c.addMethod(r,t[n],t)):e.Array.each(n,function(e){c.importMethod(t,e)})},c.one=function(t){var n=null,r,i;if(t){if(typeof t=="string"){t=c._fromString(t);if(!t)return null}else if(t.getDOMNode)return t;if(t.nodeType||e.DOM.isWindow(t)){i=t.uniqueID&&t.nodeType!==9?t.uniqueID:t._yuid,n=c._instances[i],r=n?n._node:null;if(!n||r&&t!==r)n=new c(t),t.nodeType!=11&&(c._instances[n[u]]=n)}}return n},c.DEFAULT_SETTER=function(t,r){var i=this._stateProxy,s;return t.indexOf(n)>-1?(s=t,t=t.split(n),e.Object.setValue(i,t,r)):typeof i[t]!="undefined"&&(i[t]=r),r},c.DEFAULT_GETTER=function(t){var r=this._stateProxy,i;return t.indexOf&&t.indexOf(n)>-1?i=e.Object.getValue(r,t.split(n)):typeof r[t]!="undefined"&&(i=r[t]),i},e.mix(c.prototype,{DATA_PREFIX:"data-",toString:function(){var e=this[u]+": not bound to a node",t=this._node,n,i,s;return t&&(n=t.attributes,i=n&&n.id?t.getAttribute("id"):null,s=n&&n.className?t.getAttribute("className"):null,e=t[r],i&&(e+="#"+i),s&&(e+="."+s.replace(" ",".")),e+=" "+this[u]),e},get:function(e){var t;return this._getAttr?t=this._getAttr(e):t=this._get(e),t?t=c.scrubVal(t,this):t===null&&(t=null),t},_get:function(e){var t=c.ATTRS[e],n;return t&&t.getter?n=t.getter.call(this):c.re_aria.test(e)?n=this._node.getAttribute(e,2):n=c.DEFAULT_GETTER.apply(this,arguments),n},set:function(e,t){var n=c.ATTRS[e];return this._setAttr?this._setAttr.apply(this,arguments):n&&n.setter?n.setter.call(this,t,e):c.re_aria.test(e)?this._node.setAttribute(e,t):c.DEFAULT_SETTER.apply(this,arguments),this},setAttrs:function(t){return this._setAttrs?this._setAttrs(t):e.Object.each(t,function(e,t){this.set(t,e)},this),this},getAttrs:function(t){var n={};return this._getAttrs?this._getAttrs(t):e.Array.each(t,function(e,t){n[e]=this.get(e)},this),n},compareTo:function(e){var t=this._node;return e&&e._node&&(e=e._node),t===e},inDoc:function(e){var t=this._node;e=e?e._node||e:t[s];if(e.documentElement)return l.contains(e.documentElement,t)},getById:function(t){var n=this._node,r=l.byId(t,n[s]);return r&&l.contains(n,r)?r=e.one(r):r=null,r},ancestor:function(t,n,r){return arguments.length===2&&(typeof n=="string"||typeof n=="function")&&(r=n),e.one(l.ancestor(this._node,h(t),n,h(r)))},ancestors:function(t,n,r){return arguments.length===2&&(typeof n=="string"||typeof n=="function")&&(r=n),e.all(l.ancestors(this._node,h(t),n,h(r)))},previous:function(t,n){return e.one(l.elementByAxis(this._node,"previousSibling",h(t),n))},next:function(t,n){return e.one(l.elementByAxis(this._node,"nextSibling",h(t),n))},siblings:function(t){return e.all(l.siblings(this._node,h(t)))},one:function(t){return e.one(e.Selector.query(t,this._node,!0))},all:function(t){var n=e.all(e.Selector.query(t,this._node));return n._query=t,n._queryRoot=this._node,n},test:function(t){return e.Selector.test(this._node,t)},remove:function(e){var t=this._node;return t&&t.parentNode&&t.parentNode.removeChild(t),e&&this.destroy(),this},replace:function(e){var t=this._node;return typeof e=="string"&&(e=c.create(e)),t.parentNode.replaceChild(c.getDOMNode(e),t),this},replaceChild:function(t,n){return typeof t=="string"&&(t=l.create(t)),e.one(this._node.replaceChild(c.getDOMNode(t),c.getDOMNode(n)))},destroy:function(t){var n=e.config.doc.uniqueID?"uniqueID":"_yuid",r;this.purge(),this.unplug&&this.unplug(),this.clearData(),t&&e.NodeList.each(this.all("*"),function(t){r=c._instances[t[n]],r?r.destroy():e.Event.purgeElement(t)}),this._node=null,this._stateProxy=null,delete c._instances[this._yuid]},invoke:function(e,t,n,r,i,s){var o=this._node,u;return t&&t._node&&(t=t._node),n&&n._node&&(n=n._node),u=o[e](t,n,r,i,s),c.scrubVal(u,this)},swap:e.config.doc.documentElement.swapNode?function(e){this._node.swapNode(c.getDOMNode(e))}:function(e){e=c.getDOMNode(e);var t=this._node,n=e.parentNode,r=e.nextSibling;return r===t?n.insertBefore(t,e):e===t.nextSibling?n.insertBefore(e,t):(t.parentNode.replaceChild(e,t),l.addHTML(n,t,r)),this},hasMethod:function(e){var t=this._node;return!(!(t&&e in t&&typeof t[e]!="unknown")||typeof t[e]!="function"&&String(t[e]).indexOf("function")!==1)},isFragment:function(){return this.get("nodeType")===11},empty:function(){return this.get("childNodes").remove().destroy(!0),this},getDOMNode:function(){return this._node}},!0),e.Node=c,e.one=c.one;var p=function(t){var n=[];t&&(typeof t=="string"?(this._query=t,t=e.Selector.query(t)):t.nodeType||l.isWindow(t)?t=[t]:t._node?t=[t._node]:t[0]&&t[0]._node?(e.Array.each(t,function(e){e._node&&n.push(e._node)}),t=n):t=e.Array(t,0,!0)),this._nodes=t||[]};p.NAME="NodeList",p.getDOMNodes=function(e){return e&&e._nodes?e._nodes:e},p.each=function(t,n,r){var i=t._nodes;i&&i.length&&e.Array.each(i,n,r||t)},p.addMethod=function(t,n,r){t&&n&&(p.prototype[t]=function(){var t=[],i=arguments;return e.Array.each(this._nodes,function(s){var o=s.uniqueID&&s.nodeType!==9?"uniqueID":"_yuid",u=e.Node._instances[s[o]],a,f;u||(u=p._getTempNode(s)),a=r||u,f=n.apply(a,i),f!==undefined&&f!==u&&(t[t.length]=f)}),t.length?t:this})},p.importMethod=function(t,n,r){typeof n=="string"?(r=r||n,p.addMethod(n,t[n])):e.Array.each(n,function(e){p.importMethod(t,e)})},p._getTempNode=function(t){var n=p._tempNode;return n||(n=e.Node.create("<div></div>"),p._tempNode=n),n._node=t,n._stateProxy=t,n},e.mix(p.prototype,{_invoke:function(e,t,n){var r=n?[]:this;return this.each(function(i){var s=i[e].apply(i,t);n&&r.push(s)}),r},item:function(t){return e.one((this._nodes||[])[t])},each:function(t,n){var r=this;return e.Array.each(this._nodes,function(i,s){return i=e.one(i),t.call(n||i,i,s,r)}),r},batch:function(t,n){var r=this;return e.Array.each(this._nodes,function(i,s){var o=e.Node._instances[i[u]];return o||(o=p._getTempNode(i)),t.call(n||o,o,s,r)}),r},some:function(t,n){var r=this;return e.Array.some(this._nodes,function(i,s){return i=e.one(i),n=n||i,t.call(n,i,s,r)})},toFrag:function(){return e.one(e.DOM._nl2frag(this._nodes))},indexOf:function(t){return e.Array.indexOf(this._nodes,e.Node.getDOMNode(t))},filter:function(t){return e.all(e.Selector.filter(this._nodes,t))},modulus:function(t,n){n=n||0;var r=[];return p.each(this,function(e,i){i%t===n&&r.push(e)}),e.all(r)},odd:function(){return this.modulus(2,1)},even:function(){return this.modulus(2)},destructor:function(){},refresh:function(){var t,n=this._nodes,r=this._query,i=this._queryRoot;return r&&(i||n&&n[0]&&n[0].ownerDocument&&(i=n[0].ownerDocument),this._nodes=e.Selector.query(r,i)),this},size:function(){return this._nodes.length},isEmpty:function(){return this._nodes.length<1},toString:function(){var e="",t=this[u]+": not bound to any nodes",n=this._nodes,i;return n&&n[0]&&(i=n[0],e+=i[r],i.id&&(e+="#"+i.id),i.className&&(e+="."+i.className.replace(" ",".")),n.length>1&&(e+="...["+n.length+" items]")),e||t},getDOMNodes:function(){return this._nodes}},!0),p.importMethod(e.Node.prototype,["destroy","empty","remove","set"]),p.prototype.get=function(t){var n=[],r=this._nodes,i=!1,s=p._getTempNode,o,u;return r[0]&&(o=e.Node._instances[r[0]._yuid]||s(r[0]),u=o._get(t),u&&u.nodeType&&(i=!0)),e.Array.each(r,function(r){o=e.Node._instances[r._yuid],o||(o=s(r)),u=o._get(t),i||(u=e.Node.scrubVal(u,o)),n.push(u)}),i?e.all(n):n},e.NodeList=p,e.all=function(e){return new p(e)},e.Node.all=e.all;var d=e.NodeList,v=Array.prototype,m={concat:1,pop:0,push:0,shift:0,slice:1,splice:1,unshift:0};e.Object.each(m,function(t,n){d.prototype[n]=function(){var r=[],i=0,s,o;while(typeof (s=arguments[i++])!="undefined")r.push(s._node||s._nodes||s);return o=v[n].apply(this._nodes,r),t?o=e.all(o):o=e.Node.scrubVal(o),o}}),e.Array.each(["removeChild","hasChildNodes","cloneNode","hasAttribute","scrollIntoView","getElementsByTagName","focus","blur","submit","reset","select","createCaption"],function(t){e.Node.prototype[t]=function(e,n,r){var i=this.invoke(t,e,n,r);return i}}),e.Node.prototype.removeAttribute=function(e){var t=this._node;return t&&t.removeAttribute(e,0),this},e.Node.importMethod(e.DOM,["contains","setAttribute","getAttribute","wrap","unwrap","generateID"]),e.NodeList.importMethod(e.Node.prototype,["getAttribute","setAttribute","removeAttribute","unwrap","wrap","generateID"])},"3.7.3",{requires:["dom-core","selector"]});
diff --git a/js/yui3/node-deprecated/node-deprecated-min.js b/js/yui3/node-deprecated/node-deprecated-min.js
new file mode 100644
index 000000000..a55bf2326
--- /dev/null
+++ b/js/yui3/node-deprecated/node-deprecated-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-deprecated",function(e,t){var n=e.Node;n.ATTRS.data={getter:function(){return this._dataVal},setter:function(e){return this._dataVal=e,e},value:null},e.get=n.get=function(){return n.one.apply(n,arguments)},e.mix(n.prototype,{query:function(e){return this.one(e)},queryAll:function(e){return this.all(e)},each:function(e,t){return t=t||this,e.call(t,this)},item:function(e){return this},size:function(){return this._node?1:0}})},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/node-event-delegate/node-event-delegate-min.js b/js/yui3/node-event-delegate/node-event-delegate-min.js
new file mode 100644
index 000000000..2aaa0b07d
--- /dev/null
+++ b/js/yui3/node-event-delegate/node-event-delegate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-event-delegate",function(e,t){e.Node.prototype.delegate=function(t){var n=e.Array(arguments,0,!0),r=e.Lang.isObject(t)&&!e.Lang.isArray(t)?1:2;return n.splice(r,0,this._node),e.delegate.apply(e,n)}},"3.7.3",{requires:["node-base","event-delegate"]});
diff --git a/js/yui3/node-event-html5/node-event-html5-min.js b/js/yui3/node-event-html5/node-event-html5-min.js
new file mode 100644
index 000000000..18e6012c6
--- /dev/null
+++ b/js/yui3/node-event-html5/node-event-html5-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-event-html5",function(e,t){e.mix(e.Node.DOM_EVENTS,{DOMActivate:1,DOMContentLoaded:1,afterprint:1,beforeprint:1,canplay:1,canplaythrough:1,durationchange:1,emptied:1,ended:1,formchange:1,forminput:1,hashchange:1,input:1,invalid:1,loadedmetadata:1,loadeddata:1,loadstart:1,offline:1,online:1,pagehide:1,pageshow:1,pause:1,play:1,playing:1,popstate:1,progress:1,ratechange:1,readystatechange:1,redo:1,seeking:1,seeked:1,show:1,stalled:1,suspend:1,timeupdate:1,undo:1,volumechange:1,waiting:1})},"3.7.3",{requires:["node-base"]});
diff --git a/js/yui3/node-event-simulate/node-event-simulate-min.js b/js/yui3/node-event-simulate/node-event-simulate-min.js
new file mode 100644
index 000000000..1e350f839
--- /dev/null
+++ b/js/yui3/node-event-simulate/node-event-simulate-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-event-simulate",function(e,t){e.Node.prototype.simulate=function(t,n){e.Event.simulate(e.Node.getDOMNode(this),t,n)},e.Node.prototype.simulateGesture=function(t,n,r){e.Event.simulateGesture(this,t,n,r)}},"3.7.3",{requires:["node-base","event-simulate","gesture-simulate"]});
diff --git a/js/yui3/node-flick/assets/node-flick-core.css b/js/yui3/node-flick/assets/node-flick-core.css
new file mode 100644
index 000000000..43adfbbaa
--- /dev/null
+++ b/js/yui3/node-flick/assets/node-flick-core.css
@@ -0,0 +1,14 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-flick {
+ position:relative;
+ overflow:hidden;
+}
+
+.yui3-flick-content {
+ position:relative;
+}
diff --git a/js/yui3/node-flick/assets/skins/sam/node-flick.css b/js/yui3/node-flick/assets/skins/sam/node-flick.css
new file mode 100644
index 000000000..30020432b
--- /dev/null
+++ b/js/yui3/node-flick/assets/skins/sam/node-flick.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-flick{position:relative;overflow:hidden}.yui3-flick-content{position:relative}#yui3-css-stamp.skin-sam-node-flick{display:none}
diff --git a/js/yui3/node-flick/node-flick-min.js b/js/yui3/node-flick/node-flick-min.js
new file mode 100644
index 000000000..f4a2ed852
--- /dev/null
+++ b/js/yui3/node-flick/node-flick-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-flick",function(e,t){function b(e){b.superclass.constructor.apply(this,arguments)}var n="host",r="parentNode",i="boundingBox",s="offsetHeight",o="offsetWidth",u="scrollHeight",a="scrollWidth",f="bounce",l="minDistance",c="minVelocity",h="bounceDistance",p="deceleration",d="step",v="duration",m="easing",g="flick",y=e.ClassNameManager.getClassName;b.ATTRS={deceleration:{value:.98},bounce:{value:.7},bounceDistance:{value:150},minVelocity:{value:0},minDistance:{value:10},boundingBox:{valueFn:function(){return this.get(n).get(r)}},step:{value:10},duration:{value:null},easing:{value:null}},b.NAME="pluginFlick",b.NS="flick",e.extend(b,e.Plugin.Base,{initializer:function(t){this._node=this.get(n),this._renderClasses(),this.setBounds(),this._node.on(g,e.bind(this._onFlick,this),{minDistance:this.get(l),minVelocity:this.get(c)})},setBounds:function(){var e=this.get(i),t=this._node,n=e.get(s),r=e.get(o),f=t.get(u),l=t.get(a);f>n&&(this._maxY=f-n,this._minY=0,this._scrollY=!0),l>r&&(this._maxX=l-r,this._minX=0,this._scrollX=!0),this._x=this._y=0,t.set("top",this._y+"px"),t.set("left",this._x+"px")},_renderClasses:function(){this.get(i).addClass(b.CLASS_NAMES.box),this._node.addClass(b.CLASS_NAMES.content)},_onFlick:function(e){this._v=e.flick.velocity,this._flick=!0,this._flickAnim()},_flickAnim:function(){var t=this._y,n=this._x,r=this._maxY,i=this._minY,s=this._maxX,o=this._minX,u=this._v,a=this.get(d),l=this.get(p),c=this.get(f);this._v=u*l,this._snapToEdge=!1,this._scrollX&&(n-=u*a),this._scrollY&&(t-=u*a),Math.abs(u).toFixed(4)<=b.VELOCITY_THRESHOLD?(this._flick=!1,this._killTimer(!this._exceededYBoundary&&!this._exceededXBoundary),this._scrollX&&(n<o?(this._snapToEdge=!0,this._setX(o)):n>s&&(this._snapToEdge=!0,this._setX(s))),this._scrollY&&(t<i?(this._snapToEdge=!0,this._setY(i)):t>r&&(this._snapToEdge=!0,this._setY(r)))):(this._scrollX&&(n<o||n>s)&&(this._exceededXBoundary=!0,this._v*=c),this._scrollY&&(t<i||t>r)&&(this._exceededYBoundary=!0,this._v*=c),this._scrollX&&this._setX(n),this._scrollY&&this._setY(t),this._flickTimer=e.later(a,this,this._flickAnim))},_setX:function(e){this._move(e,null,this.get(v),this.get(m))},_setY:function(e){this._move(null,e,this.get(v),this.get(m))},_move:function(e,t,n,r){e!==null?e=this._bounce(e):e=this._x,t!==null?t=this._bounce(t):t=this._y,n=n||this._snapToEdge?b.SNAP_DURATION:0,r=r||this._snapToEdge?b.SNAP_EASING:b.EASING,this._x=e,this._y=t,this._anim(e,t,n,r)},_anim:function(t,n,r,i){var s=t*-1,o=n*-1,u={duration:r/1e3,easing:i};e.Transition.useNative?u.transform="translate("+s+"px,"+o+"px)":(u.left=s+"px",u.top=o+"px"),this._node.transition(u)},_bounce:function(e,t){var n=this.get(f),r=this.get(h),i=n?-r:0;return t=n?t+r:t,n||(e<i?e=i:e>t&&(e=t)),e},_killTimer:function(){this._flickTimer&&this._flickTimer.cancel()}},{VELOCITY_THRESHOLD:.015,SNAP_DURATION:400,EASING:"cubic-bezier(0, 0.1, 0, 1.0)",SNAP_EASING:"ease-out",CLASS_NAMES:{box:y(b.NS),content:y(b.NS,"content")}}),e.Plugin.Flick=b},"3.7.3",{requires:["classnamemanager","transition","event-flick","plugin"],skinnable:!0});
diff --git a/js/yui3/node-focusmanager/node-focusmanager-min.js b/js/yui3/node-focusmanager/node-focusmanager-min.js
new file mode 100644
index 000000000..34758cd36
--- /dev/null
+++ b/js/yui3/node-focusmanager/node-focusmanager-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-focusmanager",function(e,t){var n="activeDescendant",r="id",i="disabled",s="tabIndex",o="focused",u="focusClass",a="circular",f="UI",l="key",c=n+"Change",h="host",p={37:!0,38:!0,39:!0,40:!0},d={a:!0,button:!0,input:!0,object:!0},v=e.Lang,m=e.UA,g=function(){g.superclass.constructor.apply(this,arguments)};g.ATTRS={focused:{value:!1,readOnly:!0},descendants:{getter:function(e){return this.get(h).all(e)}},activeDescendant:{setter:function(t){var n=v.isNumber,i=e.Attribute.INVALID_VALUE,s=this._descendantsMap,o=this._descendants,u,a,f;return n(t)?(u=t,a=u):t instanceof e.Node&&s?(u=s[t.get(r)],n(u)?a=u:a=i):a=i,o&&(f=o.item(u),f&&f.get("disabled")&&(a=i)),a}},keys:{value:{next:null,previous:null}},focusClass:{},circular:{value:!0}},e.extend(g,e.Plugin.Base,{_stopped:!0,_descendants:null,_descendantsMap:null,_focusedNode:null,_lastNodeIndex:0,_eventHandlers:null,_initDescendants:function(){var t=this.get("descendants"),o={},u=-1,a,f=this.get(n),l,c,h=0;v.isUndefined(f)&&(f=-1);if(t){a=t.size();for(h=0;h<a;h++)l=t.item(h),u===-1&&!l.get(i)&&(u=h),f<0&&parseInt(l.getAttribute(s,2),10)===0&&(f=h),l&&l.set(s,-1),c=l.get(r),c||(c=e.guid(),l.set(r,c)),o[c]=h;f<0&&(f=0),l=t.item(f);if(!l||l.get(i))l=t.item(u),f=u;this._lastNodeIndex=a-1,this._descendants=t,this._descendantsMap=o,this.set(n,f),l&&l.set(s,0)}},_isDescendant:function(e){return e.get(r)in this._descendantsMap},_removeFocusClass:function(){var e=this._focusedNode,t=this.get(u),n;t&&(n=v.isString(t)?t:t.className),e&&n&&e.removeClass(n)},_detachKeyHandler:function(){var e=this._prevKeyHandler,t=this._nextKeyHandler;e&&e.detach(),t&&t.detach()},_preventScroll:function(e){p[e.keyCode]&&this._isDescendant(e.target)&&e.preventDefault()},_fireClick:function(e){var t=e.target,n=t.get("nodeName").toLowerCase();e.keyCode===13&&(!d[n]||n==="a"&&!t.getAttribute("href"))&&t.simulate("click")},_attachKeyHandler:function(){this._detachKeyHandler();var t=this.get("keys.next"),n=this.get("keys.previous"),r=this.get(h),i=this._eventHandlers;n&&(this._prevKeyHandler=e.on(l,e.bind(this._focusPrevious,this),r,n)),t&&(this._nextKeyHandler=e.on(l,e.bind(this._focusNext,this),r,t)),m.opera&&i.push(r.on("keypress",this._preventScroll,this)),m.opera||i.push(r.on("keypress",this._fireClick,this))},_detachEventHandlers:function(){this._detachKeyHandler();var t=this._eventHandlers;t&&(e.Array.each(t,function(e){e.detach()}),this._eventHandlers=null)},_attachEventHandlers:function(){var t=this._descendants,n,r,i;t&&t.size()&&(n=this._eventHandlers||[],r=this.get(h).get("ownerDocument"),n.length===0&&(n.push(r.on("focus",this._onDocFocus,this)),n.push(r.on("mousedown",this._onDocMouseDown,this)),n.push(this.after("keysChange",this._attachKeyHandler)),n.push(this.after("descendantsChange",this._initDescendants)),n.push(this.after(c,this._afterActiveDescendantChange)),i=this.after("focusedChange",e.bind(function(e){e.newVal&&(this._attachKeyHandler(),i.detach())},this)),n.push(i)),this._eventHandlers=n)},_onDocMouseDown:function(e){var t=this.get(h),n=e.target,r=t.contains(n),i,s=function(e){var n=!1;return e.compareTo(t)||(n=this._isDescendant(e)?e:s.call(this,e.get("parentNode"))),n};r&&(i=s.call(this,n),i?n=i:!i&&this.get(o)&&(this._set(o,!1),this._onDocFocus(e))),r&&this._isDescendant(n)?this.focus(n):m.webkit&&this.get(o)&&(!r||r&&!this._isDescendant(n))&&(this._set(o,!1),this._onDocFocus(e))},_onDocFocus:function(e){var t=this._focusTarget||e.target,n=this.get(o),r=this.get(u),i=this._focusedNode,s;this._focusTarget&&(this._focusTarget=null),this.get(h).contains(t)?(s=this._isDescendant(t),!n&&s?n=!0:n&&!s&&(n=!1)):n=!1,r&&(i&&(!i.compareTo(t)||!n)&&this._removeFocusClass(),s&&n&&(r.fn?(t=r.fn(t),t.addClass(r.className)):t.addClass(r),this._focusedNode=t)),this._set(o,n)},_focusNext:function(e,t){var r=t||this.get(n),i;this._isDescendant(e.target)&&r<=this._lastNodeIndex&&(r+=1,r===this._lastNodeIndex+1&&this.get(a)&&(r=0),i=this._descendants.item(r),i&&(i.get("disabled")?this._focusNext(e,r):this.focus(r))),this._preventScroll(e)},_focusPrevious:function(e,t){var r=t||this.get(n),i;this._isDescendant(e.target)&&r>=0&&(r-=1,r===-1&&this.get(a)&&(r=this._lastNodeIndex),i=this._descendants.item(r),i&&(i.get("disabled")?this._focusPrevious(e,r):this.focus(r))),this._preventScroll(e)},_afterActiveDescendantChange:function(e){var t=this._descendants.item(e.prevVal);t&&t.set(s,-1),t=this._descendants.item(e.newVal),t&&t.set(s,0)},initializer:function(e){this.start()},destructor:function(){this.stop(),this.get(h).focusManager=null},focus:function(e){v.isUndefined(e)&&(e=this.get(n)),this.set(n,e,{src:f});var t=this._descendants.item(this.get(n));t&&(t.focus(),m.opera&&t.get("nodeName").toLowerCase()==="button"&&(this._focusTarget=t))},blur:function(){var e;this.get(o)&&(e=this._descendants.item(this.get(n)),e&&(e.blur(),this._removeFocusClass()),this._set(o,!1,{src:f}))},start:function(){this._stopped&&(this._initDescendants(),this._attachEventHandlers(),this._stopped=!1)},stop:function(){this._stopped||(this._detachEventHandlers(),this._descendants=null,this._focusedNode=null,this._lastNodeIndex=0,this._stopped=!0)},refresh:function(){this._initDescendants(),this._eventHandlers||this._attachEventHandlers()}}),g.NAME="nodeFocusManager",g.NS="focusManager",e.namespace("Plugin"),e.Plugin.NodeFocusManager=g},"3.7.3",{requires:["attribute","node","plugin","node-event-simulate","event-key","event-focus"]});
diff --git a/js/yui3/node-load/node-load-min.js b/js/yui3/node-load/node-load-min.js
new file mode 100644
index 000000000..6de04d2c1
--- /dev/null
+++ b/js/yui3/node-load/node-load-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-load",function(e,t){e.Node.prototype._ioComplete=function(t,n,r){var i=r[0],s=r[1],o,u;n&&n.responseText&&(u=n.responseText,i&&(o=e.DOM.create(u),u=e.Selector.query(i,o)),this.setContent(u)),s&&s.call(this,t,n)},e.Node.prototype.load=function(t,n,r){typeof n=="function"&&(r=n,n=null);var i={context:this,on:{complete:this._ioComplete},arguments:[n,r]};return e.io(t,i),this}},"3.7.3",{requires:["node-base","io-base"]});
diff --git a/js/yui3/node-menunav/assets/node-menunav-core.css b/js/yui3/node-menunav/assets/node-menunav-core.css
new file mode 100644
index 000000000..39ec29876
--- /dev/null
+++ b/js/yui3/node-menunav/assets/node-menunav-core.css
@@ -0,0 +1,175 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-menu .yui3-menu {
+
+ position: absolute;
+ z-index: 1;
+
+}
+
+
+.yui3-menu .yui3-shim {
+
+ /*
+ Styles for the <iframe> shim used to prevent <select> elements from poking through
+ submenus in IE < 7. Note: For peformance, creation of the <iframe> shim for each submenu
+ is deferred until it is initially made visible by the user.
+ */
+
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: -1;
+ opacity: 0;
+ filter: alpha(opacity=0); /* For IE since it doesn't implement the CSS3 "opacity" property. */
+ border: none;
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ width: 100%;
+
+}
+
+.yui3-menu-hidden {
+
+ /*
+ Position hidden menus outside the viewport boundaries to prevent them from
+ triggering scrollbars on the viewport.
+ */
+
+ top: -10000px;
+ left: -10000px;
+
+ /*
+ Using "visibility:hidden" over "display" none because:
+
+ 1) As the "position" property for submenus is set to "absolute", they are out of
+ the document flow and take up no space. Therefore, from that perspective use of
+ "display:none" is redundant.
+
+ 2) According to MSDN use of "display:none" is more expensive:
+ "Display is the more expensive of the two CSS properties, so if you are
+ making elements appear and disappear often, visibility will be faster."
+ (See http://msdn.microsoft.com/en-us/library/bb264005(VS.85).aspx)
+ */
+
+ visibility: hidden;
+
+}
+
+.yui3-menu li {
+
+ list-style-type: none;
+
+}
+
+.yui3-menu ul,
+.yui3-menu li {
+
+ margin: 0;
+ padding: 0;
+
+}
+
+.yui3-menu-label,
+.yui3-menuitem-content {
+
+ text-align: left;
+ white-space: nowrap;
+ display: block;
+
+}
+
+.yui3-menu-horizontal li {
+
+ float: left;
+ width: auto;
+
+}
+
+.yui3-menu-horizontal li li {
+
+ float: none;
+
+}
+
+.yui3-menu-horizontal ul {
+
+ /*
+ Use of "zoom" sets the "hasLayout" property to "true" in IE (< 8). When "hasLayout" is
+ set to "true", an element can clear its floated descendents. For more:
+ http://msdn.microsoft.com/en-gb/library/ms533776(VS.85).aspx
+ */
+
+ *zoom: 1;
+
+}
+
+.yui3-menu-horizontal ul ul {
+
+ /*
+ No need to clear <ul>s of submenus of horizontal menus since <li>s of submenus
+ aren't floated.
+ */
+
+ *zoom: normal;
+
+}
+
+.yui3-menu-horizontal>.yui3-menu-content>ul:after {
+
+ /* Self-clearing solution for Opera, Webkit, Gecko and IE > 7 */
+
+ content: "";
+ display: block;
+ clear: both;
+ line-height: 0;
+ font-size: 0;
+ visibility: hidden;
+
+}
+
+
+/*
+ The following two rules are for IE 7. Triggering "hasLayout" (via use of "zoom") prevents
+ first-tier submenus from hiding when the mouse is moving from an menu label in a root menu to
+ its corresponding submenu.
+*/
+
+.yui3-menu-content {
+
+ *zoom: 1;
+
+}
+
+
+.yui3-menu-hidden .yui3-menu-content {
+
+ *zoom: normal;
+
+}
+
+
+/*
+ The following two rules are for IE 6 (Standards Mode and Quirks Mode) and IE 7 (Quirks Mode
+ only). Triggering "hasLayout" (via use of "zoom") fixes a bug in IE where mousing mousing off
+ the text node of menuitem or menu label will incorrectly trigger the mouseout event.
+*/
+
+.yui3-menuitem-content,
+.yui3-menu-label {
+
+ _zoom: 1;
+
+}
+
+.yui3-menu-hidden .yui3-menuitem-content,
+.yui3-menu-hidden .yui3-menu-label {
+
+ _zoom: normal;
+
+}
diff --git a/js/yui3/node-menunav/assets/skins/night/horizontal-menu-submenu-indicator.png b/js/yui3/node-menunav/assets/skins/night/horizontal-menu-submenu-indicator.png
new file mode 100644
index 000000000..7940437b7
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/night/horizontal-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/node-menunav/assets/skins/night/node-menunav.css b/js/yui3/node-menunav/assets/skins/night/node-menunav.css
new file mode 100644
index 000000000..e2d1f6844
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/night/node-menunav.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-menu .yui3-menu{position:absolute;z-index:1}.yui3-menu .yui3-shim{position:absolute;top:0;left:0;z-index:-1;opacity:0;filter:alpha(opacity=0);border:0;margin:0;padding:0;height:100%;width:100%}.yui3-menu-hidden{top:-10000px;left:-10000px;visibility:hidden}.yui3-menu li{list-style-type:none}.yui3-menu ul,.yui3-menu li{margin:0;padding:0}.yui3-menu-label,.yui3-menuitem-content{text-align:left;white-space:nowrap;display:block}.yui3-menu-horizontal li{float:left;width:auto}.yui3-menu-horizontal li li{float:none}.yui3-menu-horizontal ul{*zoom:1}.yui3-menu-horizontal ul ul{*zoom:normal}.yui3-menu-horizontal>.yui3-menu-content>ul:after{content:"";display:block;clear:both;line-height:0;font-size:0;visibility:hidden}.yui3-menu-content{*zoom:1}.yui3-menu-hidden .yui3-menu-content{*zoom:normal}.yui3-menuitem-content,.yui3-menu-label{_zoom:1}.yui3-menu-hidden .yui3-menuitem-content,.yui3-menu-hidden .yui3-menu-label{_zoom:normal}.yui3-skin-night .yui3-menu-content,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-content{font-size:100%;line-height:2.25;*line-height:1.45;border:solid 1px #303030;background:#151515}.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-content{font-size:100%}.yui3-skin-night .yui3-menu-horizontal .yui3-menu-content{line-height:2;*line-height:1.9;background-color:#3b3c3d;background:-moz-linear-gradient(0% 100% 90deg,#242526 0,#3b3c3d 96%,#2c2d2f 100%);background:-webkit-gradient(linear,left bottom,left top,from(#242526),color-stop(0.96,#3b3c3d),to(#2c2d2f));padding:0}.yui3-skin-night .yui3-menu ul,.yui3-skin-night .yui3-menu ul ul{margin-top:3px;padding-top:3px;border-top:solid 1px #303030}.yui3-skin-night .yui3-menu ul.first-of-type{border:0;margin:0;padding:0}.yui3-skin-night .yui3-menu-horizontal ul{padding:0;margin:0;border:0}.yui3-skin-night .yui3-menu li,.yui3-skin-night .yui3-menu .yui3-menu li{_border-bottom:solid 1px #151515}.yui3-skin-night .yui3-menu-horizontal li{_border-bottom:0}.yui3-skin-night .yui3-menubuttonnav li{border-right:solid 1px #ccc}.yui3-skin-night .yui3-splitbuttonnav li{border-right:solid 1px #303030}.yui3-skin-night .yui3-menubuttonnav li li,.yui3-skin-night .yui3-splitbuttonnav li li{border-right:0}.yui3-skin-night .yui3-menu-label,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-label,.yui3-skin-night .yui3-menuitem-content,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menuitem-content{padding:0 1em;color:#fff;text-decoration:none;cursor:default;float:none;border:0;margin:0}.yui3-skin-night .yui3-menu-horizontal .yui3-menu-label,.yui3-skin-night .yui3-menu-horizontal .yui3-menuitem-content{padding:0 10px;border-style:solid;border-color:#303030;border-width:1px 0;margin:-1px 0;float:left;width:auto}.yui3-skin-night .yui3-menu-label,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-label{background:url(vertical-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-night .yui3-menu-horizontal .yui3-menu-label{background:0}.yui3-skin-night .yui3-menubuttonnav .yui3-menu-label,.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label{background-image:none}.yui3-skin-night .yui3-menubuttonnav .yui3-menu-label{padding-right:0}.yui3-skin-night .yui3-menubuttonnav .yui3-menu-label em{font-style:normal;padding-right:20px;display:block;background:url(horizontal-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label{padding:0}.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label a{float:left;width:auto;color:#fff;text-decoration:none;cursor:default;padding:0 5px 0 10px}.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label .yui3-menu-toggle{padding:0;border-left:solid 1px #303030;width:15px;overflow:hidden;text-indent:-1000px;background:url(horizontal-menu-submenu-indicator.png) 3px center no-repeat}.yui3-skin-night .yui3-menu-label-active,.yui3-skin-night .yui3-menu-label-menuvisible,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-label-active,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menu-label-menuvisible{background-color:#292a2a}.yui3-skin-night .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-night .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content{background-image:none;background-color:#292a2a;background:-moz-linear-gradient(0% 100% 90deg,#252626 0,#333434 100%);background:-webkit-gradient(linear,left top,left bottom,from(#333434),to(#252626));border-left-width:0;margin-left:0}.yui3-skin-night .yui3-menu-horizontal .yui3-menu-label-active,.yui3-skin-night .yui3-menu-horizontal .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-night .yui3-menu-horizontal .yui3-menu-label-menuvisible{border-color:#303030;background-color:#555658;background:-moz-linear-gradient(0% 100% 90deg,#343536 0,#555658 96%,#3e3f41 100%);background:-webkit-gradient(linear,left bottom,left top,from(#343536),color-stop(0.96,#555658),to(#3e3f41))}.yui3-skin-night .yui3-menubuttonnav .yui3-menu-label-active,.yui3-skin-night .yui3-menubuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-night .yui3-menubuttonnav .yui3-menu-label-menuvisible,.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label-active,.yui3-skin-night .yui3-splitbuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-left-width:1px;margin-left:-1px}.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-color:#303030;background:transparent}.yui3-skin-night .yui3-splitbuttonnav .yui3-menu-label-menuvisible .yui3-menu-toggle{border-color:#303030;background-color:#505050}#yui3-css-stamp.skin-night-node-menunav{display:none}
diff --git a/js/yui3/node-menunav/assets/skins/night/vertical-menu-submenu-indicator.png b/js/yui3/node-menunav/assets/skins/night/vertical-menu-submenu-indicator.png
new file mode 100644
index 000000000..d997b8e4c
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/night/vertical-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-indicator.png b/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-indicator.png
new file mode 100644
index 000000000..a2482ac79
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-toggle.png b/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-toggle.png
new file mode 100644
index 000000000..4379f817d
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/sam/horizontal-menu-submenu-toggle.png
Binary files differ
diff --git a/js/yui3/node-menunav/assets/skins/sam/node-menunav.css b/js/yui3/node-menunav/assets/skins/sam/node-menunav.css
new file mode 100644
index 000000000..b95397473
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/sam/node-menunav.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-menu .yui3-menu{position:absolute;z-index:1}.yui3-menu .yui3-shim{position:absolute;top:0;left:0;z-index:-1;opacity:0;filter:alpha(opacity=0);border:0;margin:0;padding:0;height:100%;width:100%}.yui3-menu-hidden{top:-10000px;left:-10000px;visibility:hidden}.yui3-menu li{list-style-type:none}.yui3-menu ul,.yui3-menu li{margin:0;padding:0}.yui3-menu-label,.yui3-menuitem-content{text-align:left;white-space:nowrap;display:block}.yui3-menu-horizontal li{float:left;width:auto}.yui3-menu-horizontal li li{float:none}.yui3-menu-horizontal ul{*zoom:1}.yui3-menu-horizontal ul ul{*zoom:normal}.yui3-menu-horizontal>.yui3-menu-content>ul:after{content:"";display:block;clear:both;line-height:0;font-size:0;visibility:hidden}.yui3-menu-content{*zoom:1}.yui3-menu-hidden .yui3-menu-content{*zoom:normal}.yui3-menuitem-content,.yui3-menu-label{_zoom:1}.yui3-menu-hidden .yui3-menuitem-content,.yui3-menu-hidden .yui3-menu-label{_zoom:normal}.yui3-skin-sam .yui3-menu-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:93%;line-height:1.5;*line-height:1.45;border:solid 1px #808080;background:#fff;padding:3px 0}.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content{font-size:100%}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-content{line-height:2;*line-height:1.9;background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0;padding:0}.yui3-skin-sam .yui3-menu ul,.yui3-skin-sam .yui3-menu ul ul{margin-top:3px;padding-top:3px;border-top:solid 1px #ccc}.yui3-skin-sam .yui3-menu ul.first-of-type{border:0;margin:0;padding:0}.yui3-skin-sam .yui3-menu-horizontal ul{padding:0;margin:0;border:0}.yui3-skin-sam .yui3-menu li,.yui3-skin-sam .yui3-menu .yui3-menu li{_border-bottom:solid 1px #fff}.yui3-skin-sam .yui3-menu-horizontal li{_border-bottom:0}.yui3-skin-sam .yui3-menubuttonnav li{border-right:solid 1px #ccc}.yui3-skin-sam .yui3-splitbuttonnav li{border-right:solid 1px #808080}.yui3-skin-sam .yui3-menubuttonnav li li,.yui3-skin-sam .yui3-splitbuttonnav li li{border-right:0}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label,.yui3-skin-sam .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-content{padding:0 1em;color:#000;text-decoration:none;cursor:default;float:none;border:0;margin:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-content{padding:0 10px;border-style:solid;border-color:#808080;border-width:1px 0;margin:-1px 0;float:left;width:auto}.yui3-skin-sam .yui3-menu-label,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label{background:url(vertical-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label{background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{background-image:none}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label{padding-right:0}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label em{font-style:normal;padding-right:20px;display:block;background:url(horizontal-menu-submenu-indicator.png) right center no-repeat}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label{padding:0}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label a{float:left;width:auto;color:#000;text-decoration:none;cursor:default;padding:0 5px 0 10px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label .yui3-menu-toggle{padding:0;border-left:solid 1px #ccc;width:15px;overflow:hidden;text-indent:-1000px;background:url(horizontal-menu-submenu-indicator.png) 3px center no-repeat}.yui3-skin-sam .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-active,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-menuvisible{background-color:#b3d4ff}.yui3-skin-sam .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content{background-image:none;background-color:#b3d4ff;border-left-width:0;margin-left:0}.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-active,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-menuvisible{border-color:#7d98b8;background:url(../../../../assets/skins/sam/sprite.png) repeat-x 0 -1700px}.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-menubuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-menuvisible,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-active,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menuitem-active .yui3-menuitem-content,.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-left-width:1px;margin-left:-1px}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible{border-color:#808080;background:transparent}.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible .yui3-menu-toggle{border-color:#7d98b8;background:url(horizontal-menu-submenu-toggle.png) left center no-repeat}#yui3-css-stamp.skin-sam-node-menunav{display:none}
diff --git a/js/yui3/node-menunav/assets/skins/sam/vertical-menu-submenu-indicator.png b/js/yui3/node-menunav/assets/skins/sam/vertical-menu-submenu-indicator.png
new file mode 100644
index 000000000..cfc46b8ac
--- /dev/null
+++ b/js/yui3/node-menunav/assets/skins/sam/vertical-menu-submenu-indicator.png
Binary files differ
diff --git a/js/yui3/node-menunav/node-menunav-min.js b/js/yui3/node-menunav/node-menunav-min.js
new file mode 100644
index 000000000..add1c1a79
--- /dev/null
+++ b/js/yui3/node-menunav/node-menunav-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-menunav",function(e,t){var n=e.UA,r=e.later,i=e.ClassNameManager.getClassName,s="menu",o="menuitem",u="hidden",a="parentNode",f="children",l="offsetHeight",c="offsetWidth",h="px",p="id",d=".",v="handledMouseOut",m="handledMouseOver",g="active",y="label",b="a",w="mousedown",E="keydown",S="click",x="",T="first-of-type",N="role",C="presentation",k="descendants",L="UI",A="activeDescendant",O="useARIA",M="aria-hidden",_="content",D="host",P=A+"Change",H="autoSubmenuDisplay",B="mouseOutHideDelay",j=i(s),F=i(s,u),I=i(s,"horizontal"),q=i(s,y),R=i(s,y,g),U=i(s,y,s+"visible"),z=i(o),W=i(o,g),X=d+j,V=d+i(s,"toggle"),$=d+i(s,_),J=d+q,K=">"+$+">ul>li>a",Q=">"+$+">ul>li>"+J+">a:first-child",G=function(e){var t=e.previous(),n;return t||(n=e.get(a).get(f),t=n.item(n.size()-1)),t},Y=function(e){var t=e.next();return t||(t=e.get(a).get(f).item(0)),t},Z=function(e){var t=!1;return e&&(t=e.get("nodeName").toLowerCase()===b),t},et=function(e){return e.hasClass(z)},tt=function(e){return e.hasClass(q)},nt=function(e){return e.hasClass(I)},rt=function(e){return e.hasClass(U)},it=function(e){return Z(e)?e:e.one(b)},st=function(e,t,n){var r;return e&&(e.hasClass(t)&&(r=e),!r&&n&&(r=e.ancestor(d+t))),r},ot=function(e){return e.ancestor(X)},ut=function(e,t){return st(e,j,t)},at=function(e,t){var n;return e&&(n=st(e,z,t)),n},ft=function(e,t){var n;return e&&(t?n=st(e,q,t):n=st(e,q)||e.one(d+q)),n},lt=function(e,t){var n;return e&&(n=at(e,t)||ft(e,t)),n},ct=function(e){return lt(e.one("li"))},ht=function(e){return et(e)?W:R},pt=function(e,t){return e&&!e[m]&&(e.compareTo(t)||e.contains(t))},dt=function(e,t){return e&&!e[v]&&!e.compareTo(t)&&!e.contains(t)},vt=function(){vt.superclass.constructor.apply(this,arguments)};vt.NAME="nodeMenuNav",vt.NS="menuNav",vt.SHIM_TEMPLATE_TITLE="Menu Stacking Shim",vt.SHIM_TEMPLATE='<iframe frameborder="0" tabindex="-1" class="'+i("shim")+'" title="'+vt.SHIM_TEMPLATE_TITLE+'" src="javascript:false;"></iframe>',vt.ATTRS={useARIA:{value:!0,writeOnce:!0,lazyAdd:!1,setter:function(t){var n=this.get(D),r,u,a,f;t&&(n.set(N,s),n.all("ul,li,"+$).set(N,C),n.all(d+i(o,_)).set(N,o),n.all(d+q).each(function(t){r=t,u=t.one(V),u&&(u.set(N,C),r=u.previous()),r.set(N,o),r.set("aria-haspopup",!0),a=t.next(),a&&(a.set(N,s),r=a.previous(),u=r.one(V),u&&(r=u),f=e.stamp(r),r.get(p)||r.set(p,f),a.set("aria-labelledby",f),a.set(M,!0))}))}},autoSubmenuDisplay:{value:!0,writeOnce:!0},submenuShowDelay:{value:250,writeOnce:!0},submenuHideDelay:{value:250,writeOnce:!0},mouseOutHideDelay:{value:750,writeOnce:!0}},e.extend(vt,e.Plugin.Base,{_rootMenu:null,_activeItem:null,_activeMenu:null,_hasFocus:!1,_blockMouseEvent:!1,_currentMouseX:0,_movingToSubmenu:!1,_showSubmenuTimer:null,_hideSubmenuTimer:null,_hideAllSubmenusTimer:null,_firstItem:null,initializer:function(t){var n=this,r=this.get(D),i=[],s;r&&(n._rootMenu=r,r.all("ul:first-child").addClass(T),r.all(X).addClass(F),i.push(r.on("mouseover",n._onMouseOver,n)),i.push(r.on("mouseout",n._onMouseOut,n)),i.push(r.on("mousemove",n._onMouseMove,n)),i.push(r.on(w,n._toggleSubmenuDisplay,n)),i.push(e.on("key",n._toggleSubmenuDisplay,r,"down:13",n)),i.push(r.on(S,n._toggleSubmenuDisplay,n)),i.push(r.on("keypress",n._onKeyPress,n)),i.push(r.on(E,n._onKeyDown,n)),s=r.get("ownerDocument"),i.push(s.on(w,n._onDocMouseDown,n)),i.push(s.on("focus",n._onDocFocus,n)),this._eventHandlers=i,n._initFocusManager())},destructor:function(){var t=this._eventHandlers;t&&(e.Array.each(t,function(e){e.detach()}),this._eventHandlers=null),this.get(D).unplug("focusManager")},_isRoot:function(e){return this._rootMenu.compareTo(e)},_getTopmostSubmenu:function(e){var t=this,n=ot(e),r;return n?t._isRoot(n)?r=e:r=t._getTopmostSubmenu(n):r=e,r},_clearActiveItem:function(){var e=this,t=e._activeItem;t&&t.removeClass(ht(t)),e._activeItem=null},_setActiveItem:function(e){var t=this;e&&(t._clearActiveItem(),e.addClass(ht(e)),t._activeItem=e)},_focusItem:function(e){var t=this,n,r;e&&t._hasFocus&&(n=ot(e),r=it(e),n&&!n.compareTo(t._activeMenu)&&(t._activeMenu=n,t._initFocusManager()),t._focusManager.focus(r))},_showMenu:function(t){var r=ot(t),i=t.get(a),s=i.getXY();this.get(O)&&t.set(M,!1),nt(r)?s[1]=s[1]+i.get(l):s[0]=s[0]+i.get(c),t.setXY(s),n.ie<8&&(n.ie===6&&!t.hasIFrameShim&&(t.appendChild(e.Node.create(vt.SHIM_TEMPLATE)),t.hasIFrameShim=!0),t.setStyles({height:x,width:x}),t.setStyles({height:t.get(l)+h,width:t.get(c)+h})),t.previous().addClass(U),t.removeClass(F)},_hideMenu:function(e,t){var n=this,r=e.previous(),i;r.removeClass(U),t&&(n._focusItem(r),n._setActiveItem(r)),i=e.one(d+W),i&&i.removeClass(W),e.setStyles({left:x,top:x}),e.addClass(F),n.get(O)&&e.set(M,!0)},_hideAllSubmenus:function(t){var n=this;t.all(X).each(e.bind(function(e){n._hideMenu(e)},n))},_cancelShowSubmenuTimer:function(){var e=this,t=e._showSubmenuTimer;t&&(t.cancel(),e._showSubmenuTimer=null)},_cancelHideSubmenuTimer:function(){var e=this,t=e._hideSubmenuTimer;t&&(t.cancel(),e._hideSubmenuTimer=null)},_initFocusManager:function(){var t=this,n=t._rootMenu,r=t._activeMenu||n,i=t._isRoot(r)?x:"#"+r.get("id"),s=t._focusManager,o,u,a;nt(r)?(u=i+K+","+i+Q,o={next:"down:39",previous:"down:37"}):(u=i+K,o={next:"down:40",previous:"down:38"}),s?(s.set(A,-1),s.set(k,u),s.set("keys",o)):(n.plug(e.Plugin.NodeFocusManager,{descendants:u,keys:o,circular:!0}),s=n.focusManager,a="#"+n.get("id")+X+" a,"+V,n.all(a).set("tabIndex",-1),s.on(P,this._onActiveDescendantChange,s,this),s.after(P,this._afterActiveDescendantChange,s,this),t._focusManager=s)},_onActiveDescendantChange:function(e,t){e.src===L&&t._activeMenu&&!t._movingToSubmenu&&t._hideAllSubmenus(t._activeMenu)},_afterActiveDescendantChange:function(e,t){var n;e.src===L&&(n=lt(this.get(k).item(e.newVal),!0),t._setActiveItem(n))},_onDocFocus:function(e){var t=this,n=t._activeItem,r=e.target,i;t._rootMenu.contains(r)?t._hasFocus?(i=ot(r),t._activeMenu.compareTo(i)||(t._activeMenu=i,t._initFocusManager(),t._focusManager.set(A,r),t._setActiveItem(lt(r,!0)))):(t._hasFocus=!0,n=lt(r,!0),n&&t._setActiveItem(n)):(t._clearActiveItem(),t._cancelShowSubmenuTimer(),t._hideAllSubmenus(t._rootMenu),t._activeMenu=t._rootMenu,t._initFocusManager(),t._focusManager.set(A,0),t._hasFocus=!1)},_onMenuMouseOver:function(e,t){var n=this,r=n._hideAllSubmenusTimer;r&&(r.cancel(),n._hideAllSubmenusTimer=null),n._cancelHideSubmenuTimer(),e&&!e.compareTo(n._activeMenu)&&(n._activeMenu=e,n._hasFocus&&n._initFocusManager()),n._movingToSubmenu&&nt(e)&&(n._movingToSubmenu=!1)},_hideAndFocusLabel:function(){var e=this,t=e._activeMenu,n;e._hideAllSubmenus(e._rootMenu),t&&(n=e._getTopmostSubmenu(t),e._focusItem(n.previous()))},_onMenuMouseOut:function(e,t){var n=this,i=n._activeMenu,s=t.relatedTarget,o=n._activeItem,u,a;i&&!i.contains(s)&&(u=ot(i),u&&!u.contains(s)?n.get(B)>0&&(n._cancelShowSubmenuTimer(),n._hideAllSubmenusTimer=r(n.get(B),n,n._hideAndFocusLabel)):o&&(a=ot(o),n._isRoot(a)||n._focusItem(a.previous())))},_onMenuLabelMouseOver:function(e,t){var n=this,i=n._activeMenu,s=n._isRoot(i),o=n.get(H)&&s||!s,u=n.get("submenuShowDelay"),a,f=function(t){n._cancelHideSubmenuTimer(),n._cancelShowSubmenuTimer(),rt(e)||(a=e.next(),a&&(n._hideAllSubmenus(i),n._showSubmenuTimer=r(t,n,n._showMenu,a)))};n._focusItem(e),n._setActiveItem(e),o&&(n._movingToSubmenu?n._hoverTimer=r(u,n,function(){f(0)}):f(u))},_onMenuLabelMouseOut:function(e,t){var n=this,i=n._isRoot(n._activeMenu),s=n.get(H)&&i||!i,o=t.relatedTarget,u=e.next(),a=n._hoverTimer;a&&a.cancel(),n._clearActiveItem(),s&&(n._movingToSubmenu&&!n._showSubmenuTimer&&u?n._hideSubmenuTimer=r(n.get("submenuHideDelay"),n,n._hideMenu,u):!n._movingToSubmenu&&u&&(!o||o&&!u.contains(o)&&!o.compareTo(u))&&(n._cancelShowSubmenuTimer(),n._hideMenu(u)))},_onMenuItemMouseOver:function(e,t){var n=this,r=n._activeMenu,i=n._isRoot(r),s=n.get(H)&&i||!i;n._focusItem(e),n._setActiveItem(e),s&&!n._movingToSubmenu&&n._hideAllSubmenus(r)},_onMenuItemMouseOut:function(e,t){this._clearActiveItem()},_onVerticalMenuKeyDown:function(e){var t=this,n=t._activeMenu,r=t._rootMenu,i=e.target,s=!1,o=e.keyCode,u,f,l,c;switch(o){case 37:f=ot(n),f&&nt(f)?(t._hideMenu(n),l=G(n.get(a)),c=lt(l),c&&(tt(c)?(u=c.next(),u?(t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u))):(t._focusItem(c),t._setActiveItem(c))):(t._focusItem(c),t._setActiveItem(c)))):t._isRoot(n)||t._hideMenu(n,!0),s=!0;break;case 39:tt(i)?(u=i.next(),u&&(t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u)))):nt(r)&&(u=t._getTopmostSubmenu(n),l=Y(u.get(a)),c=lt(l),t._hideAllSubmenus(r),c&&(tt(c)?(u=c.next(),u?(t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u))):(t._focusItem(c),t._setActiveItem(c))):(t._focusItem(c),t._setActiveItem(c)))),s=!0}s&&e.preventDefault()},_onHorizontalMenuKeyDown:function(e){var t=this,n=t._activeMenu,r=e.target,i=lt(r,!0),s=!1,o=e.keyCode,u;o===40&&(t._hideAllSubmenus(n),tt(i)&&(u=i.next(),u&&(t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u))),s=!0)),s&&e.preventDefault()},_onMouseMove:function(e){var t=this;r(10,t,function(){t._currentMouseX=e.pageX})},_onMouseOver:function(e){var t=this,n,r,i,s,o;t._blockMouseEvent?t._blockMouseEvent=!1:(n=e.target,r=ut(n,!0),i=ft(n,!0),o=at(n,!0),pt(r,n)&&(t._onMenuMouseOver(r,e),r[m]=!0,r[v]=!1,s=ot(r),s&&(s[v]=!0,s[m]=!1)),pt(i,n)&&(t._onMenuLabelMouseOver(i,e),i[m]=!0,i[v]=!1),pt(o,n)&&(t._onMenuItemMouseOver(o,e),o[m]=!0,o[v]=!1))},_onMouseOut:function(e){var t=this,n=t._activeMenu,r=!1,i,s,o,u,a,f;t._movingToSubmenu=n&&!nt(n)&&e.pageX-5>t._currentMouseX,i=e.target,s=e.relatedTarget,o=ut(i,!0),u=ft(i,!0),f=at(i,!0),dt(u,s)&&(t._onMenuLabelMouseOut(u,e),u[v]=!0,u[m]=!1),dt(f,s)&&(t._onMenuItemMouseOut(f,e),f[v]=!0,f[m]=!1),u&&(a=u.next(),a&&s&&(s.compareTo(a)||a.contains(s))&&(r=!0));if(dt(o,s)||r)t._onMenuMouseOut(o,e),o[v]=!0,o[m]=!1},_toggleSubmenuDisplay:function(e){var t=this,r=e.target,i=ft(r,!0),s=e.type,o,u,a,f,l,c;if(i){o=Z(r)?r:r.ancestor(Z);if(o){a=o.getAttribute("href",2),f=a.indexOf("#"),l=a.length;if(f===0&&l>1){c=a.substr(1,l),u=i.next();if(u&&u.get(p)===c){if(s===w||s===E)(n.opera||n.gecko||n.ie)&&s===E&&!t._preventClickHandle&&(t._preventClickHandle=t._rootMenu.on("click",function(e){e.preventDefault(),t._preventClickHandle.detach(),t._preventClickHandle=null})),s==w&&(e.preventDefault(),e.stopImmediatePropagation(),t._hasFocus=!0),t._isRoot(ot(r))?rt(i)?(t._hideMenu(u),t._focusItem(i),t._setActiveItem(i)):(t._hideAllSubmenus(t._rootMenu),t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u))):t._activeItem==i?(t._showMenu(u),t._focusItem(ct(u)),t._setActiveItem(ct(u))):i._clickHandle||(i._clickHandle=i.on("click",function(){t._hideAllSubmenus(t._rootMenu),t._hasFocus=!1,t._clearActiveItem(),i._clickHandle.detach(),i._clickHandle=null}));s===S&&e.preventDefault()}}}}},_onKeyPress:function(e){switch(e.keyCode){case 37:case 38:case 39:case 40:e.preventDefault()}},_onKeyDown:function(e){var t=this,i=t._activeItem,s=e.target,o=ot(s),u;o&&(t._activeMenu=o,nt(o)?t._onHorizontalMenuKeyDown(e):t._onVerticalMenuKeyDown(e),e.keyCode===27&&(t._isRoot(o)?i&&(tt(i)&&rt(i)?(u=i.next(),u&&t._hideMenu(u)):(t._focusManager.blur(),t._clearActiveItem(),t._hasFocus=!1)):(n.opera?r(0,t,function(){t._hideMenu(o,!0)}):t._hideMenu(o,!0),e.stopPropagation(),t._blockMouseEvent=n.gecko?!0:!1)))},_onDocMouseDown:function(e){var t=this,r=t._rootMenu,i=e.target;!r.compareTo(i)&&!r.contains(i)&&(t._hideAllSubmenus(r),n.webkit&&(t._hasFocus=!1,t._clearActiveItem()))}}),e.namespace("Plugin"),e.Plugin.NodeMenuNav=vt},"3.7.3",{requires:["node","classnamemanager","plugin","node-focusmanager"],skinnable:!0});
diff --git a/js/yui3/node-pluginhost/node-pluginhost-min.js b/js/yui3/node-pluginhost/node-pluginhost-min.js
new file mode 100644
index 000000000..33aee8a96
--- /dev/null
+++ b/js/yui3/node-pluginhost/node-pluginhost-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-pluginhost",function(e,t){e.Node.plug=function(){var t=e.Array(arguments);return t.unshift(e.Node),e.Plugin.Host.plug.apply(e.Base,t),e.Node},e.Node.unplug=function(){var t=e.Array(arguments);return t.unshift(e.Node),e.Plugin.Host.unplug.apply(e.Base,t),e.Node},e.mix(e.Node,e.Plugin.Host,!1,null,1),e.NodeList.prototype.plug=function(){var t=arguments;return e.NodeList.each(this,function(n){e.Node.prototype.plug.apply(e.one(n),t)}),this},e.NodeList.prototype.unplug=function(){var t=arguments;return e.NodeList.each(this,function(n){e.Node.prototype.unplug.apply(e.one(n),t)}),this}},"3.7.3",{requires:["node-base","pluginhost"]});
diff --git a/js/yui3/node-screen/node-screen-min.js b/js/yui3/node-screen/node-screen-min.js
new file mode 100644
index 000000000..3227c2848
--- /dev/null
+++ b/js/yui3/node-screen/node-screen-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-screen",function(e,t){e.each(["winWidth","winHeight","docWidth","docHeight","docScrollX","docScrollY"],function(t){e.Node.ATTRS[t]={getter:function(){var n=Array.prototype.slice.call(arguments);return n.unshift(e.Node.getDOMNode(this)),e.DOM[t].apply(this,n)}}}),e.Node.ATTRS.scrollLeft={getter:function(){var t=e.Node.getDOMNode(this);return"scrollLeft"in t?t.scrollLeft:e.DOM.docScrollX(t)},setter:function(t){var n=e.Node.getDOMNode(this);n&&("scrollLeft"in n?n.scrollLeft=t:(n.document||n.nodeType===9)&&e.DOM._getWin(n).scrollTo(t,e.DOM.docScrollY(n)))}},e.Node.ATTRS.scrollTop={getter:function(){var t=e.Node.getDOMNode(this);return"scrollTop"in t?t.scrollTop:e.DOM.docScrollY(t)},setter:function(t){var n=e.Node.getDOMNode(this);n&&("scrollTop"in n?n.scrollTop=t:(n.document||n.nodeType===9)&&e.DOM._getWin(n).scrollTo(e.DOM.docScrollX(n),t))}},e.Node.importMethod(e.DOM,["getXY","setXY","getX","setX","getY","setY","swapXY"]),e.Node.ATTRS.region={getter:function(){var t=this.getDOMNode(),n;return t&&!t.tagName&&t.nodeType===9&&(t=t.documentElement),e.DOM.isWindow(t)?n=e.DOM.viewportRegion(t):n=e.DOM.region(t),n}},e.Node.ATTRS.viewportRegion={getter:function(){return e.DOM.viewportRegion(e.Node.getDOMNode(this))}},e.Node.importMethod(e.DOM,"inViewportRegion"),e.Node.prototype.intersect=function(t,n){var r=e.Node.getDOMNode(this);return e.instanceOf(t,e.Node)&&(t=e.Node.getDOMNode(t)),e.DOM.intersect(r,t,n)},e.Node.prototype.inRegion=function(t,n,r){var i=e.Node.getDOMNode(this);return e.instanceOf(t,e.Node)&&(t=e.Node.getDOMNode(t)),e.DOM.inRegion(i,t,n,r)}},"3.7.3",{requires:["dom-screen","node-base"]});
diff --git a/js/yui3/node-scroll-info/node-scroll-info-min.js b/js/yui3/node-scroll-info/node-scroll-info-min.js
new file mode 100644
index 000000000..104319baf
--- /dev/null
+++ b/js/yui3/node-scroll-info/node-scroll-info-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-scroll-info",function(e,t){var n="scroll",r="scrollDown",i="scrollLeft",s="scrollRight",o="scrollUp",u="scrollToBottom",a="scrollToLeft",f="scrollToRight",l="scrollToTop";e.Plugin.ScrollInfo=e.Base.create("scrollInfoPlugin",e.Plugin.Base,[],{initializer:function(e){this._host=e.host,this._hostIsBody=this._host.get("nodeName").toLowerCase()==="body",this._scrollDelay=this.get("scrollDelay"),this._scrollMargin=this.get("scrollMargin"),this._scrollNode=this._getScrollNode(),this.refreshDimensions(),this._lastScroll=this.getScrollInfo(),this._bind()},destructor:function(){(new e.EventHandle(this._events)).detach(),delete this._events},getOffscreenNodes:function(t,n){typeof n=="undefined"&&(n=this._scrollMargin);var r=this._lastScroll,i=this._host.all(t||"*"),s=r.scrollBottom+n,o=r.scrollLeft-n,u=r.scrollRight+n,a=r.scrollTop-n,f=this;return i.filter(function(t){var n=e.DOM.getXY(t),r=n[0]-f._left,i=n[1]-f._top,l,c;return r>=o&&r<u&&i>=a&&i<s?!1:(l=i+t.offsetHeight,c=r+t.offsetWidth,c<u&&c>=o&&l<s&&l>=a?!1:!0)})},getOnscreenNodes:function(t,n){typeof n=="undefined"&&(n=this._scrollMargin);var r=this._lastScroll,i=this._host.all(t||"*"),s=r.scrollBottom+n,o=r.scrollLeft-n,u=r.scrollRight+n,a=r.scrollTop-n,f=this;return i.filter(function(t){var n=e.DOM.getXY(t),r=n[0]-f._left,i=n[1]-f._top,l,c;return r>=o&&r<u&&i>=a&&i<s?!0:(l=i+t.offsetHeight,c=r+t.offsetWidth,c<u&&c>=o&&l<s&&l>=a?!0:!1)})},getScrollInfo:function(){var e=this._scrollNode,t=this._lastScroll,n=this._scrollMargin,r=e.scrollLeft,i=e.scrollHeight,s=e.scrollTop,o=e.scrollWidth,u=s+this._height,a=r+this._width;return{atBottom:u>i-n,atLeft:r<n,atRight:a>o-n,atTop:s<n,isScrollDown:t&&s>t.scrollTop,isScrollLeft:t&&r<t.scrollLeft,isScrollRight:t&&r>t.scrollLeft,isScrollUp:t&&s<t.scrollTop,scrollBottom:u,scrollHeight:i,scrollLeft:r,scrollRight:a,scrollTop:s,scrollWidth:o}},refreshDimensions:function(){var t=this._hostIsBody,n=t&&e.UA.ios,r=e.config.win,i;t&&e.UA.webkit?i=e.config.doc.documentElement:i=this._scrollNode,this._height=n?r.innerHeight:i.clientHeight,this._left=i.offsetLeft,this._top=i.offsetTop,this._width=n?r.innerWidth:i.clientWidth},_bind:function(){var t=e.one("win");this._events=[this.after({scrollDelayChange:this._afterScrollDelayChange,scrollMarginChange:this._afterScrollMarginChange}),t.on("windowresize",this._afterResize,this),(this._hostIsBody?t:this._host).after("scroll",this._afterScroll,this)]},_getScrollNode:function(){return this._hostIsBody&&!e.UA.webkit?e.config.doc.documentElement:e.Node.getDOMNode(this._host)},_triggerScroll:function(t){var c=this.getScrollInfo(),h=e.merge(t,c),p=this._lastScroll;this._lastScroll=c,this.fire(n,h),c.isScrollLeft?this.fire(i,h):c.isScrollRight&&this.fire(s,h),c.isScrollUp?this.fire(o,h):c.isScrollDown&&this.fire(r,h),c.atBottom&&(!p.atBottom||c.scrollHeight>p.scrollHeight)&&this.fire(u,h),c.atLeft&&!p.atLeft&&this.fire(a,h),c.atRight&&(!p.atRight||c.scrollWidth>p.scrollWidth)&&this.fire(f,h),c.atTop&&!p.atTop&&this.fire(l,h)},_afterResize:function(e){this.refreshDimensions()},_afterScroll:function(e){var t=this;clearTimeout(this._scrollTimeout),this._scrollTimeout=setTimeout(function(){t._triggerScroll(e)},this._scrollDelay)},_afterScrollDelayChange:function(e){this._scrollDelay=e.newVal},_afterScrollMarginChange:function(e){this._scrollMargin=e.newVal}},{NS:"scrollInfo",ATTRS:{scrollDelay:{value:50},scrollMargin:{value:50}}})},"3.7.3",{requires:["base-build","dom-screen","event-resize","node-pluginhost","plugin"]});
diff --git a/js/yui3/node-style/node-style-min.js b/js/yui3/node-style/node-style-min.js
new file mode 100644
index 000000000..90e6e06bb
--- /dev/null
+++ b/js/yui3/node-style/node-style-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("node-style",function(e,t){(function(e){e.mix(e.Node.prototype,{setStyle:function(t,n){return e.DOM.setStyle(this._node,t,n),this},setStyles:function(t){return e.DOM.setStyles(this._node,t),this},getStyle:function(t){return e.DOM.getStyle(this._node,t)},getComputedStyle:function(t){return e.DOM.getComputedStyle(this._node,t)}}),e.NodeList.importMethod(e.Node.prototype,["getStyle","getComputedStyle","setStyle","setStyles"])})(e)},"3.7.3",{requires:["dom-style","node-base"]});
diff --git a/js/yui3/oop/oop-min.js b/js/yui3/oop/oop-min.js
new file mode 100644
index 000000000..af3be061b
--- /dev/null
+++ b/js/yui3/oop/oop-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("oop",function(e,t){function a(t,n,i,s,o){if(t&&t[o]&&t!==e)return t[o].call(t,n,i);switch(r.test(t)){case 1:return r[o](t,n,i);case 2:return r[o](e.Array(t,0,!0),n,i);default:return e.Object[o](t,n,i,s)}}var n=e.Lang,r=e.Array,i=Object.prototype,s="_~yuim~_",o=i.hasOwnProperty,u=i.toString;e.augment=function(t,n,r,i,s){var a=t.prototype,f=a&&n,l=n.prototype,c=a||t,h,p,d,v,m;return s=s?e.Array(s):[],f&&(p={},d={},v={},h=function(e,t){if(r||!(t in a))u.call(e)==="[object Function]"?(v[t]=e,p[t]=d[t]=function(){return m(this,e,arguments)}):p[t]=e},m=function(e,t,r){for(var i in v)o.call(v,i)&&e[i]===d[i]&&(e[i]=v[i]);return n.apply(e,s),t.apply(e,r)},i?e.Array.each(i,function(e){e in l&&h(l[e],e)}):e.Object.each(l,h,null,!0)),e.mix(c,p||l,r,i),f||n.apply(c,s),t},e.aggregate=function(t,n,r,i){return e.mix(t,n,r,i,0,!0)},e.extend=function(t,n,r,s){(!n||!t)&&e.error("extend failed, verify dependencies");var o=n.prototype,u=e.Object(o);return t.prototype=u,u.constructor=t,t.superclass=o,n!=Object&&o.constructor==i.constructor&&(o.constructor=n),r&&e.mix(u,r,!0),s&&e.mix(t,s,!0),t},e.each=function(e,t,n,r){return a(e,t,n,r,"each")},e.some=function(e,t,n,r){return a(e,t,n,r,"some")},e.clone=function(t,r,i,o,u,a){if(!n.isObject(t))return t;if(e.instanceOf(t,YUI))return t;var f,l=a||{},c,h=e.each;switch(n.type(t)){case"date":return new Date(t);case"regexp":return t;case"function":return t;case"array":f=[];break;default:if(t[s])return l[t[s]];c=e.guid(),f=r?{}:e.Object(t),t[s]=c,l[c]=t}return!t.addEventListener&&!t.attachEvent&&h(t,function(n,a){(a||a===0)&&(!i||i.call(o||this,n,a,this,t)!==!1)&&a!==s&&a!="prototype"&&(this[a]=e.clone(n,r,i,o,u||t,l))},f),a||(e.Object.each(l,function(e,t){if(e[s])try{delete e[s]}catch(n){e[s]=null}},this),l=null),f},e.bind=function(t,r){var i=arguments.length>2?e.Array(arguments,2,!0):null;return function(){var s=n.isString(t)?r[t]:t,o=i?i.concat(e.Array(arguments,0,!0)):arguments;return s.apply(r||s,o)}},e.rbind=function(t,r){var i=arguments.length>2?e.Array(arguments,2,!0):null;return function(){var s=n.isString(t)?r[t]:t,o=i?e.Array(arguments,0,!0).concat(i):arguments;return s.apply(r||s,o)}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/overlay/assets/overlay-core.css b/js/yui3/overlay/assets/overlay-core.css
new file mode 100644
index 000000000..fd0e1164b
--- /dev/null
+++ b/js/yui3/overlay/assets/overlay-core.css
@@ -0,0 +1,17 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-overlay {
+ position:absolute;
+}
+
+.yui3-overlay-hidden {
+ visibility:hidden
+}
+
+.yui3-widget-tmp-forcesize .yui3-overlay-content {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/overlay/assets/skins/night/overlay.css b/js/yui3/overlay/assets/skins/night/overlay.css
new file mode 100644
index 000000000..3ea5a89c4
--- /dev/null
+++ b/js/yui3/overlay/assets/skins/night/overlay.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-overlay{position:absolute}.yui3-overlay-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-overlay-content{overflow:hidden!important}.yui3-skin-night{background-color:#000;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:#fff}.yui3-skin-night .yui3-overlay-content ul,ol,li{margin:0;padding:0;list-style:none;zoom:1}.yui3-skin-night .yui3-overlay-content li{*float:left}.yui3-skin-night .yui3-overlay-content{background-color:#6d6e6e;-moz-box-shadow:0 0 17px rgba(0,0,0,0.58);-webkit-box-shadow:0 0 17px rgba(0,0,0,0.58);box-shadow:0 0 17px rgba(0,0,0,0.58);-moz-border-radius:7px;-webkit-border-radius:7px;border-radius:7px}.yui3-skin-night .yui3-overlay-content .yui3-widget-hd{background-color:#6d6e6e;-moz-border-radius:7px 7px 0 0;-webkit-border-radius:7px 7px 0 0;border-radius:7px 7px 0 0;color:#fff;margin:0;padding:20px 22px 0;font-size:147%}.yui3-skin-night .yui3-overlay-content .yui3-widget-bd{padding:11px 22px 17px;font-size:92%}.yui3-skin-night .yui3-overlay .yui3-widget-bd li{margin:.04em}.yui3-skin-night .yui3-overlay-content .yui3-widget-ft{background-color:#575858;border-top:solid 1px #494a4a;-moz-border-radius:0 0 7px 7px;-webkit-border-radius:0 0 7px 7px;border-radius:0 0 7px 7px;padding:17px 25px 20px;text-align:center}.yui3-skin-night .yui3-overlay-content .yui3-widget-ft li{margin:3px;display:inline-block}.yui3-skin-night .yui3-overlay-content .yui3-widget-ft li a{border:solid 1px #1b1c1c;border-radius:6px;-moz-box-shadow:0 1px #677478;-webkit-box-shadow:0 1px #677478;box-shadow:0 1px #677478;text-shadow:0 -1px 0 rgba(0,0,0,0.7);font-size:85%;text-align:center;color:#fff;padding:6px 28px;background-color:#2b2d2d;background:-moz-linear-gradient(0% 100% 90deg,#242526 0,#3b3c3d 96%,#2c2d2f 100%);background:-webkit-gradient(linear,left bottom,left top,from(#242526),color-stop(0.96,#3b3c3d),to(#2c2d2f))}.yui3-skin-night .yui3-overlay .yui3-widget-ft li:first-child{margin-left:0}.yui3-skin-night .yui3-overlay .yui3-widget-ft li:last-child{margin-right:0}.yui3-skin-night .yui3-overlay .yui3-widget-ft li:last-child a{border:solid 1px #520e00;-moz-box-shadow:0 1px #7d5d57;-webkit-box-shadow:0 1px #7d5d57;box-shadow:0 1px #7d5d57;background-color:#901704;background:-moz-linear-gradient(100% 0 270deg,#ab1c0b,#7b1400);background:-webkit-gradient(linear,left top,left bottom,from(#ab1c0b),to(#7b1400));margin-right:0}#yui3-widget-mask{background-color:#000;opacity:.5}#yui3-css-stamp.skin-night-overlay{display:none}
diff --git a/js/yui3/overlay/assets/skins/sam/overlay.css b/js/yui3/overlay/assets/skins/sam/overlay.css
new file mode 100644
index 000000000..925769f7a
--- /dev/null
+++ b/js/yui3/overlay/assets/skins/sam/overlay.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-overlay{position:absolute}.yui3-overlay-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-overlay-content{overflow:hidden!important}#yui3-css-stamp.skin-sam-overlay{display:none}
diff --git a/js/yui3/overlay/overlay-min.js b/js/yui3/overlay/overlay-min.js
new file mode 100644
index 000000000..bbf8c0fbb
--- /dev/null
+++ b/js/yui3/overlay/overlay-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("overlay",function(e,t){e.Overlay=e.Base.create("overlay",e.Widget,[e.WidgetStdMod,e.WidgetPosition,e.WidgetStack,e.WidgetPositionAlign,e.WidgetPositionConstrain])},"3.7.3",{requires:["widget","widget-stdmod","widget-position","widget-position-align","widget-stack","widget-position-constrain"],skinnable:!0});
diff --git a/js/yui3/panel/assets/panel-core.css b/js/yui3/panel/assets/panel-core.css
new file mode 100644
index 000000000..6670f46c9
--- /dev/null
+++ b/js/yui3/panel/assets/panel-core.css
@@ -0,0 +1,28 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-panel {
+ position: absolute;
+}
+.yui3-panel-hidden {
+ visibility: hidden;
+}
+.yui3-widget-tmp-forcesize .yui3-panel-content {
+ overflow: hidden !important;
+}
+.yui3-panel .yui3-widget-hd {
+ position: relative;
+}
+.yui3-panel .yui3-widget-hd .yui3-widget-buttons {
+ position: absolute;
+ top: 0;
+ right: 0;
+}
+.yui3-panel .yui3-widget-ft .yui3-widget-buttons {
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+}
diff --git a/js/yui3/panel/assets/skins/night/panel.css b/js/yui3/panel/assets/skins/night/panel.css
new file mode 100644
index 000000000..13a664070
--- /dev/null
+++ b/js/yui3/panel/assets/skins/night/panel.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-panel{position:absolute}.yui3-panel-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-panel-content{overflow:hidden!important}.yui3-panel .yui3-widget-hd{position:relative}.yui3-panel .yui3-widget-hd .yui3-widget-buttons{position:absolute;top:0;right:0}.yui3-panel .yui3-widget-ft .yui3-widget-buttons{display:inline-block;*display:inline;zoom:1}.yui3-skin-night .yui3-panel{color:#fff;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif}.yui3-skin-night .yui3-panel-content{background:#6d6e6e;-webkit-box-shadow:0 0 20px #000;-moz-box-shadow:0 0 20px #000;box-shadow:0 0 20px #000;border:1px solid black;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.yui3-skin-night .yui3-panel .yui3-widget-hd{padding:11px 57px 11px 22px;min-height:17px;_height:17px;-webkit-border-top-left-radius:7px;-webkit-border-top-right-radius:7px;-moz-border-radius-topleft:7px;-moz-border-radius-topright:7px;border-top-left-radius:7px;border-top-right-radius:7px;font-weight:bold;color:white;background-color:#555658;background:-moz-linear-gradient(0% 100% 90deg,#343536 0,#555658 96%,#3e3f41 100%);background:-webkit-gradient(linear,left bottom,left top,from(#343536),color-stop(0.96,#555658),to(#3e3f41))}.yui3-skin-night .yui3-panel .yui3-widget-hd .yui3-widget-buttons{padding:11px}.yui3-skin-night .yui3-panel .yui3-widget-bd{padding:11px 22px 17px}.yui3-skin-night .yui3-panel .yui3-widget-ft{background-color:#575858;border-top:1px solid #494a4a;padding:6px 16px 8px;text-align:center;-webkit-border-bottom-right-radius:7px;-webkit-border-bottom-left-radius:7px;-moz-border-radius-bottomright:7px;-moz-border-radius-bottomleft:7px;border-bottom-right-radius:7px;border-bottom-left-radius:7px}.yui3-skin-night .yui3-panel .yui3-widget-ft .yui3-widget-buttons{bottom:0;position:relative;right:auto;width:100%;text-align:center;padding-bottom:0;margin-left:-5px;margin-right:-5px}.yui3-skin-night .yui3-panel .yui3-widget-ft .yui3-button{margin:5px}.yui3-skin-night .yui3-panel .yui3-widget-hd .yui3-button-close{background:transparent;filter:none;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;width:22px;height:17px;padding:0;overflow:hidden;vertical-align:top;*font-size:0;*line-height:0;*letter-spacing:-1000px;*color:#86a5ec;*background:url(sprite_icons.png) no-repeat center 3px}.yui3-skin-night .yui3-panel .yui3-widget-hd .yui3-button-close:hover{background-color:#333}.yui3-skin-night .yui3-panel .yui3-widget-hd .yui3-button-close:before{content:url(sprite_icons.png);display:inline-block;text-align:center;font-size:0;line-height:0;width:22px;margin:3px 0 0 1px}.yui3-skin-night .yui3-panel-hidden .yui3-widget-hd .yui3-button-close{display:none}#yui3-css-stamp.skin-night-panel{display:none}
diff --git a/js/yui3/panel/assets/skins/night/sprite_icons.png b/js/yui3/panel/assets/skins/night/sprite_icons.png
new file mode 100644
index 000000000..34fd6cdc6
--- /dev/null
+++ b/js/yui3/panel/assets/skins/night/sprite_icons.png
Binary files differ
diff --git a/js/yui3/panel/assets/skins/sam/panel.css b/js/yui3/panel/assets/skins/sam/panel.css
new file mode 100644
index 000000000..270c58294
--- /dev/null
+++ b/js/yui3/panel/assets/skins/sam/panel.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-panel{position:absolute}.yui3-panel-hidden{visibility:hidden}.yui3-widget-tmp-forcesize .yui3-panel-content{overflow:hidden!important}.yui3-panel .yui3-widget-hd{position:relative}.yui3-panel .yui3-widget-hd .yui3-widget-buttons{position:absolute;top:0;right:0}.yui3-panel .yui3-widget-ft .yui3-widget-buttons{display:inline-block;*display:inline;zoom:1}.yui3-skin-sam .yui3-panel-content{-webkit-box-shadow:0 0 5px #333;-moz-box-shadow:0 0 5px #333;box-shadow:0 0 5px #333;border:1px solid black;background:white}.yui3-skin-sam .yui3-panel .yui3-widget-hd{padding:8px 28px 8px 8px;min-height:13px;_height:13px;color:white;background-color:#3961c5;background:-moz-linear-gradient(0% 100% 90deg,#2647a0 7%,#3d67ce 50%,#426fd9 100%);background:-webkit-gradient(linear,left bottom,left top,from(#2647a0),color-stop(0.07,#2647a0),color-stop(0.5,#3d67ce),to(#426fd9))}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-widget-buttons{padding:8px}.yui3-skin-sam .yui3-panel .yui3-widget-bd{padding:10px}.yui3-skin-sam .yui3-panel .yui3-widget-ft{background:#edf5ff;padding:8px;text-align:right}.yui3-skin-sam .yui3-panel .yui3-widget-ft .yui3-button{margin-left:8px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close{background:transparent;filter:none;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;width:13px;height:13px;padding:0;overflow:hidden;vertical-align:top;*font-size:0;*line-height:0;*letter-spacing:-1000px;*color:#86a5ec;*background:url(sprite_icons.png) no-repeat 1px 1px}.yui3-skin-sam .yui3-panel .yui3-widget-hd .yui3-button-close:before{content:url(sprite_icons.png);display:inline-block;text-align:center;font-size:0;line-height:0;width:13px;margin:1px 0 0 1px}.yui3-skin-sam .yui3-panel-hidden .yui3-widget-hd .yui3-button-close{display:none}#yui3-css-stamp.skin-sam-panel{display:none}
diff --git a/js/yui3/panel/assets/skins/sam/sprite_icons.png b/js/yui3/panel/assets/skins/sam/sprite_icons.png
new file mode 100644
index 000000000..89944ba0f
--- /dev/null
+++ b/js/yui3/panel/assets/skins/sam/sprite_icons.png
Binary files differ
diff --git a/js/yui3/panel/panel-min.js b/js/yui3/panel/panel-min.js
new file mode 100644
index 000000000..bc290cc7f
--- /dev/null
+++ b/js/yui3/panel/panel-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("panel",function(e,t){var n=e.ClassNameManager.getClassName;e.Panel=e.Base.create("panel",e.Widget,[e.WidgetPosition,e.WidgetStdMod,e.WidgetAutohide,e.WidgetButtons,e.WidgetModality,e.WidgetPositionAlign,e.WidgetPositionConstrain,e.WidgetStack],{BUTTONS:{close:{label:"Close",action:"hide",section:"header",template:'<button type="button" />',classNames:n("button","close")}}},{ATTRS:{buttons:{value:["close"]}}})},"3.7.3",{requires:["widget","widget-autohide","widget-buttons","widget-modality","widget-position","widget-position-align","widget-position-constrain","widget-stack","widget-stdmod"],skinnable:!0});
diff --git a/js/yui3/parallel/parallel-min.js b/js/yui3/parallel/parallel-min.js
new file mode 100644
index 000000000..03221f23f
--- /dev/null
+++ b/js/yui3/parallel/parallel-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("parallel",function(e,t){e.Parallel=function(t){this.config=t||{},this.results=[],this.context=this.config.context||e,this.total=0,this.finished=0},e.Parallel.prototype={results:null,total:null,finished:null,add:function(t){var n=this,r=n.total;return n.total+=1,function(){n.finished++,n.results[r]=t&&t.apply(n.context,arguments)||(arguments.length===1?arguments[0]:e.Array(arguments)),n.test()}},test:function(){var e=this;e.finished>=e.total&&e.callback&&e.callback.call(e.context,e.results,e.data)},done:function(e,t){this.callback=e,this.data=t,this.test()}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/pjax-base/pjax-base-min.js b/js/yui3/pjax-base/pjax-base-min.js
new file mode 100644
index 000000000..08ddc29e3
--- /dev/null
+++ b/js/yui3/pjax-base/pjax-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pjax-base",function(e,t){function s(){}var n=e.config.win,r=e.ClassNameManager.getClassName("pjax"),i="navigate";s.prototype={_regexURL:/^((?:[^\/#?:]+:\/\/|\/\/)[^\/]*)?([^?#]*)(\?[^#]*)?(#.*)?$/,initializer:function(){this.publish(i,{defaultFn:this._defNavigateFn}),this.get("html5")&&this._pjaxBindUI()},destructor:function(){this._pjaxEvents&&this._pjaxEvents.detach()},navigate:function(t,n){return t=this._resolveURL(t),this._navigate(t,n)?!0:(this._hasSameOrigin(t)||e.error("Security error: The new URL must be of the same origin as the current URL."),!1)},_isLinkSameOrigin:function(t){var n=e.getLocation(),r=n.protocol,i=n.hostname,s=parseInt(n.port,10)||null,o;return t.get("protocol")!==r||t.get("hostname")!==i?!1:(o=parseInt(t.get("port"),10)||null,r==="http:"?(s||(s=80),o||(o=80)):r==="https:"&&(s||(s=443),o||(o=443)),o===s)},_navigate:function(t,r){t=this._upgradeURL(t);if(!this.hasRoute(t))return!1;r=e.merge(r,{url:t});var s=this._getURL(),o,u;u=t.replace(/(#.*)$/,function(e,t,n){return o=t,e.substring(n)});if(o&&u===s.replace(/#.*$/,"")){if(!this.get("navigateOnHash"))return!1;r.hash=o}return"replace"in r||(r.replace=t===s),this.get("html5")||r.force?this.fire(i,r):r.replace?n&&n.location.replace(t):n&&(n.location=t),!0},_pjaxBindUI:function(){this._pjaxEvents||(this._pjaxEvents=e.one("body").delegate("click",this._onLinkClick,this.get("linkSelector"),this))},_defNavigateFn:function(e){this[e.replace?"replace":"save"](e.url),n&&this.get("scrollToTop")&&setTimeout(function(){n.scroll(0,0)},1)},_onLinkClick:function(e){var t,n;if(e.button!==1||e.ctrlKey||e.metaKey)return;t=e.currentTarget;if(t.get("tagName").toUpperCase()!=="A")return;if(!this._isLinkSameOrigin(t))return;n=t.get("href"),n&&this._navigate(n,{originEvent:e})&&e.preventDefault()}},s.ATTRS={linkSelector:{value:"a."+r,writeOnce:"initOnly"},navigateOnHash:{value:!1},scrollToTop:{value:!0}},e.PjaxBase=s},"3.7.3",{requires:["classnamemanager","node-event-delegate","router"]});
diff --git a/js/yui3/pjax-content/pjax-content-min.js b/js/yui3/pjax-content/pjax-content-min.js
new file mode 100644
index 000000000..765a8c0d1
--- /dev/null
+++ b/js/yui3/pjax-content/pjax-content-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pjax-content",function(e,t){function n(){}n.prototype={getContent:function(t){var n={},r=this.get("contentSelector"),i=e.Node.create(t||""),s=this.get("titleSelector"),o;return r?n.node=i.all(r).toFrag():n.node=i,s&&(o=i.one(s),o&&(n.title=o.get("text"))),n},loadContent:function(t,n,r){var i=t.url;this._request&&this._request.abort(),this.get("addPjaxParam")&&(i=i.replace(/([^#]*)(#.*)?$/,function(e,t,n){return t+=(t.indexOf("?")>-1?"&":"?")+"pjax=1",t+(n||"")})),this._request=e.io(i,{arguments:{route:{req:t,res:n,next:r},url:i},context:this,headers:{"X-PJAX":"true"},timeout:this.get("timeout"),on:{complete:this._onPjaxIOComplete,end:this._onPjaxIOEnd}})},_onPjaxIOComplete:function(e,t,n){var r=this.getContent(t.responseText),i=n.route,s=i.req,o=i.res;s.ioURL=n.url,o.content=r,o.ioResponse=t,i.next()},_onPjaxIOEnd:function(){this._request=null}},n.ATTRS={addPjaxParam:{value:!0},contentSelector:{value:null},titleSelector:{value:"title"},timeout:{value:3e4}},e.PjaxContent=n},"3.7.3",{requires:["io-base","node-base","router"]});
diff --git a/js/yui3/pjax-plugin/pjax-plugin-min.js b/js/yui3/pjax-plugin/pjax-plugin-min.js
new file mode 100644
index 000000000..2448894e1
--- /dev/null
+++ b/js/yui3/pjax-plugin/pjax-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pjax-plugin",function(e,t){e.Plugin.Pjax=e.Base.create("pjaxPlugin",e.Pjax,[e.Plugin.Base],{initializer:function(e){this.set("container",e.host)}},{NS:"pjax"})},"3.7.3",{requires:["node-pluginhost","pjax","plugin"]});
diff --git a/js/yui3/pjax/pjax-min.js b/js/yui3/pjax/pjax-min.js
new file mode 100644
index 000000000..216415251
--- /dev/null
+++ b/js/yui3/pjax/pjax-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pjax",function(e,t){var n=["loadContent","_defaultRoute"],r="error",i="load";e.Pjax=e.Base.create("pjax",e.Router,[e.PjaxBase,e.PjaxContent],{initializer:function(){this.publish(r,{defaultFn:this._defCompleteFn}),this.publish(i,{defaultFn:this._defCompleteFn})},_defaultRoute:function(e,t,n){var s=t.ioResponse,o=s.status,u=o>=200&&o<300?i:r;this.fire(u,{content:t.content,responseText:s.responseText,status:o,url:e.ioURL}),n()},_defCompleteFn:function(t){var n=this.get("container"),r=t.content;n&&r.node&&n.setHTML(r.node),r.title&&e.config.doc&&(e.config.doc.title=r.title)}},{ATTRS:{container:{value:null,setter:e.one},routes:{value:[{path:"*",callbacks:n}]}},defaultRoute:n})},"3.7.3",{requires:["pjax-base","pjax-content"]});
diff --git a/js/yui3/plugin/plugin-min.js b/js/yui3/plugin/plugin-min.js
new file mode 100644
index 000000000..5e4e0c36e
--- /dev/null
+++ b/js/yui3/plugin/plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("plugin",function(e,t){function n(t){!this.hasImpl||!this.hasImpl(e.Plugin.Base)?n.superclass.constructor.apply(this,arguments):n.prototype.initializer.apply(this,arguments)}n.ATTRS={host:{writeOnce:!0}},n.NAME="plugin",n.NS="plugin",e.extend(n,e.Base,{_handles:null,initializer:function(e){this._handles=[]},destructor:function(){if(this._handles)for(var e=0,t=this._handles.length;e<t;e++)this._handles[e].detach()},doBefore:function(e,t,n){var r=this.get("host"),i;return e in r?i=this.beforeHostMethod(e,t,n):r.on&&(i=this.onHostEvent(e,t,n)),i},doAfter:function(e,t,n){var r=this.get("host"),i;return e in r?i=this.afterHostMethod(e,t,n):r.after&&(i=this.afterHostEvent(e,t,n)),i},onHostEvent:function(e,t,n){var r=this.get("host").on(e,t,n||this);return this._handles.push(r),r},afterHostEvent:function(e,t,n){var r=this.get("host").after(e,t,n||this);return this._handles.push(r),r},beforeHostMethod:function(t,n,r){var i=e.Do.before(n,this.get("host"),t,r||this);return this._handles.push(i),i},afterHostMethod:function(t,n,r){var i=e.Do.after(n,this.get("host"),t,r||this);return this._handles.push(i),i},toString:function(){return this.constructor.NAME+"["+this.constructor.NS+"]"}}),e.namespace("Plugin").Base=n},"3.7.3",{requires:["base-base"]});
diff --git a/js/yui3/pluginhost-base/pluginhost-base-min.js b/js/yui3/pluginhost-base/pluginhost-base-min.js
new file mode 100644
index 000000000..4f895c863
--- /dev/null
+++ b/js/yui3/pluginhost-base/pluginhost-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pluginhost-base",function(e,t){function r(){this._plugins={}}var n=e.Lang;r.prototype={plug:function(e,t){var r,i,s;if(n.isArray(e))for(r=0,i=e.length;r<i;r++)this.plug(e[r]);else e&&!n.isFunction(e)&&(t=e.cfg,e=e.fn),e&&e.NS&&(s=e.NS,t=t||{},t.host=this,this.hasPlugin(s)?this[s].setAttrs&&this[s].setAttrs(t):(this[s]=new e(t),this._plugins[s]=e));return this},unplug:function(e){var t=e,r=this._plugins;if(e)n.isFunction(e)&&(t=e.NS,t&&(!r[t]||r[t]!==e)&&(t=null)),t&&(this[t]&&(this[t].destroy&&this[t].destroy(),delete this[t]),r[t]&&delete r[t]);else for(t in this._plugins)this._plugins.hasOwnProperty(t)&&this.unplug(t);return this},hasPlugin:function(e){return this._plugins[e]&&this[e]},_initPlugins:function(e){this._plugins=this._plugins||{},this._initConfigPlugins&&this._initConfigPlugins(e)},_destroyPlugins:function(){this.unplug()}},e.namespace("Plugin").Host=r},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/pluginhost-config/pluginhost-config-min.js b/js/yui3/pluginhost-config/pluginhost-config-min.js
new file mode 100644
index 000000000..2221dfb87
--- /dev/null
+++ b/js/yui3/pluginhost-config/pluginhost-config-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("pluginhost-config",function(e,t){var n=e.Plugin.Host,r=e.Lang;n.prototype._initConfigPlugins=function(t){var n=this._getClasses?this._getClasses():[this.constructor],r=[],i={},s,o,u,a,f;for(o=n.length-1;o>=0;o--)s=n[o],a=s._UNPLUG,a&&e.mix(i,a,!0),u=s._PLUG,u&&e.mix(r,u,!0);for(f in r)r.hasOwnProperty(f)&&(i[f]||this.plug(r[f]));t&&t.plugins&&this.plug(t.plugins)},n.plug=function(t,n,i){var s,o,u,a;if(t!==e.Base){t._PLUG=t._PLUG||{},r.isArray(n)||(i&&(n={fn:n,cfg:i}),n=[n]);for(o=0,u=n.length;o<u;o++)s=n[o],a=s.NAME||s.fn.NAME,t._PLUG[a]=s}},n.unplug=function(t,n){var i,s,o,u;if(t!==e.Base){t._UNPLUG=t._UNPLUG||{},r.isArray(n)||(n=[n]);for(s=0,o=n.length;s<o;s++)i=n[s],u=i.NAME,t._PLUG[u]?delete t._PLUG[u]:t._UNPLUG[u]=i}}},"3.7.3",{requires:["pluginhost-base"]});
diff --git a/js/yui3/profiler/profiler-min.js b/js/yui3/profiler/profiler-min.js
new file mode 100644
index 000000000..193c05528
--- /dev/null
+++ b/js/yui3/profiler/profiler-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("profiler",function(Y,NAME){function createReport(e){return report[e]={calls:0,max:0,min:0,avg:0,points:[]},report[e]}function saveDataPoint(e,t){var n=report[e];n||(n=createReport(e)),n.calls++,n.points.push(t),n.calls>1?(n.avg=(n.avg*(n.calls-1)+t)/n.calls,n.min=Math.min(n.min,t),n.max=Math.max(n.max,t)):(n.avg=t,n.min=t,n.max=t)}var container={},report={},stopwatches={},WATCH_STARTED=0,WATCH_STOPPED=1,WATCH_PAUSED=2,L=Y.Lang;Y.Profiler={clear:function(e){L.isString(e)?(delete report[e],delete stopwatches[e]):(report={},stopwatches={})},getOriginal:function(e){return container[e]},instrument:function(e,t){var n=function(){var n=new Date,r=t.apply(this,arguments),i=new Date;return saveDataPoint(e,i-n),r};return Y.mix(n,t),n.__yuiProfiled=!0,n.prototype=t.prototype,container[e]=t,container[e].__yuiFuncName=e,createReport(e),n},pause:function(e){var t=new Date,n=stopwatches[e];n&&n.state==WATCH_STARTED&&(n.total+=t-n.start,n.start=0,n.state=WATCH_PAUSED)},start:function(e){if(container[e])throw new Error("Cannot use '"+e+"' for profiling through start(), name is already in use.");report[e]||createReport(e),stopwatches[e]||(stopwatches[e]={state:WATCH_STOPPED,start:0,total:0}),stopwatches[e].state==WATCH_STOPPED&&(stopwatches[e].state=WATCH_STARTED,stopwatches[e].start=new Date)},stop:function(e){var t=new Date,n=stopwatches[e];n&&(n.state==WATCH_STARTED?saveDataPoint(e,n.total+(t-n.start)):n.state==WATCH_PAUSED&&saveDataPoint(e,n.total),n.start=0,n.total=0,n.state=WATCH_STOPPED)},getAverage:function(e){return report[e].avg},getCallCount:function(e){return report[e].calls},getMax:function(e){return report[e].max},getMin:function(e){return report[e].min},getFunctionReport:function(e){return report[e]},getReport:function(e){return report[e]},getFullReport:function(e){e=e||function(){return!0};if(L.isFunction(e)){var t={};for(var n in report)e(report[n])&&(t[n]=report[n]);return t}},registerConstructor:function(e,t){this.registerFunction(e,t,!0)},registerFunction:function(name,owner,registerPrototype){var funcName=name.indexOf(".")>-1?name.substring(name.lastIndexOf(".")+1):name,method,prototype;L.isObject(owner)||(owner=eval(name.substring(0,name.lastIndexOf(".")))),method=owner[funcName],prototype=method.prototype,L.isFunction(method)&&!method.__yuiProfiled&&(owner[funcName]=this.instrument(name,method),container[name].__yuiOwner=owner,container[name].__yuiFuncName=funcName,registerPrototype&&this.registerObject(name+".prototype",prototype))},registerObject:function(name,object,recurse){object=L.isObject(object)?object:eval(name),container[name]=object;for(var prop in object)typeof object[prop]=="function"?prop!="constructor"&&prop!="superclass"&&this.registerFunction(name+"."+prop,object):typeof object[prop]=="object"&&recurse&&this.registerObject(name+"."+prop,object[prop],recurse)},unregisterConstructor:function(e){L.isFunction(container[e])&&this.unregisterFunction(e,!0)},unregisterFunction:function(e,t){if(L.isFunction(container[e])){t&&this.unregisterObject(e+".prototype",container[e].prototype);var n=container[e].__yuiOwner,r=container[e].__yuiFuncName;delete container[e].__yuiOwner,delete container[e].__yuiFuncName,n[r]=container[e],delete container[e]}},unregisterObject:function(e,t){if(L.isObject(container[e])){var n=container[e];for(var r in n)typeof n[r]=="function"?this.unregisterFunction(e+"."+r):typeof n[r]=="object"&&t&&this.unregisterObject(e+"."+r,t);delete container[e]}}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/querystring-parse-simple/querystring-parse-simple-min.js b/js/yui3/querystring-parse-simple/querystring-parse-simple-min.js
new file mode 100644
index 000000000..10cb0366e
--- /dev/null
+++ b/js/yui3/querystring-parse-simple/querystring-parse-simple-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("querystring-parse-simple",function(e,t){var n=e.namespace("QueryString");n.parse=function(e,t,r){t=t||"&",r=r||"=";for(var i={},s=0,o=e.split(t),u=o.length,a;s<u;s++)a=o[s].split(r),a.length>0&&(i[n.unescape(a.shift())]=n.unescape(a.join(r)));return i},n.unescape=function(e){return decodeURIComponent(e.replace(/\+/g," "))}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/querystring-parse/querystring-parse-min.js b/js/yui3/querystring-parse/querystring-parse-min.js
new file mode 100644
index 000000000..d76de1677
--- /dev/null
+++ b/js/yui3/querystring-parse/querystring-parse-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("querystring-parse",function(e,t){var n=e.namespace("QueryString"),r=function(t){return function r(i,s){var o,u,a,f,l;return arguments.length!==2?(i=i.split(t),r(n.unescape(i.shift()),n.unescape(i.join(t)))):(i=i.replace(/^\s+|\s+$/g,""),e.Lang.isString(s)&&(s=s.replace(/^\s+|\s+$/g,""),isNaN(s)||(u=+s,s===u.toString(10)&&(s=u))),o=/(.*)\[([^\]]*)\]$/.exec(i),o?(f=o[2],a=o[1],f?(l={},l[f]=s,r(a,l)):r(a,[s])):(l={},i&&(l[i]=s),l))}},i=function(t,n){return t?e.Lang.isArray(t)?t.concat(n):!e.Lang.isObject(t)||!e.Lang.isObject(n)?[t].concat(n):s(t,n):n},s=function(e,t){for(var n in t)n&&t.hasOwnProperty(n)&&(e[n]=i(e[n],t[n]));return e};n.parse=function(t,n,s){return e.Array.reduce(e.Array.map(t.split(n||"&"),r(s||"=")),{},i)},n.unescape=function(e){return decodeURIComponent(e.replace(/\+/g," "))}},"3.7.3",{requires:["yui-base","array-extras"]});
diff --git a/js/yui3/querystring-stringify-simple/querystring-stringify-simple-min.js b/js/yui3/querystring-stringify-simple/querystring-stringify-simple-min.js
new file mode 100644
index 000000000..462922255
--- /dev/null
+++ b/js/yui3/querystring-stringify-simple/querystring-stringify-simple-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("querystring-stringify-simple",function(e,t){var n=e.namespace("QueryString"),r=encodeURIComponent;n.stringify=function(t,n){var i=[],s=n&&n.arrayKey?!0:!1,o,u,a;for(o in t)if(t.hasOwnProperty(o))if(e.Lang.isArray(t[o]))for(u=0,a=t[o].length;u<a;u++)i.push(r(s?o+"[]":o)+"="+r(t[o][u]));else i.push(r(o)+"="+r(t[o]));return i.join("&")}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/querystring-stringify/querystring-stringify-min.js b/js/yui3/querystring-stringify/querystring-stringify-min.js
new file mode 100644
index 000000000..e5cc2ba05
--- /dev/null
+++ b/js/yui3/querystring-stringify/querystring-stringify-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("querystring-stringify",function(e,t){var n=e.namespace("QueryString"),r=[],i=e.Lang;n.escape=encodeURIComponent,n.stringify=function(e,t,s){var o,u,a,f,l,c,h=t&&t.sep?t.sep:"&",p=t&&t.eq?t.eq:"=",d=t&&t.arrayKey?t.arrayKey:!1;if(i.isNull(e)||i.isUndefined(e)||i.isFunction(e))return s?n.escape(s)+p:"";if(i.isBoolean(e)||Object.prototype.toString.call(e)==="[object Boolean]")e=+e;if(i.isNumber(e)||i.isString(e))return n.escape(s)+p+n.escape(e);if(i.isArray(e)){c=[],s=d?s+"[]":s,f=e.length;for(a=0;a<f;a++)c.push(n.stringify(e[a],t,s));return c.join(h)}for(a=r.length-1;a>=0;--a)if(r[a]===e)throw new Error("QueryString.stringify. Cyclical reference");r.push(e),c=[],o=s?s+"[":"",u=s?"]":"";for(a in e)e.hasOwnProperty(a)&&(l=o+a+u,c.push(n.stringify(e[a],t,l)));return r.pop(),c=c.join(h),!c&&s?s+"=":c}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/queue-promote/queue-promote-min.js b/js/yui3/queue-promote/queue-promote-min.js
new file mode 100644
index 000000000..34913be93
--- /dev/null
+++ b/js/yui3/queue-promote/queue-promote-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("queue-promote",function(e,t){e.mix(e.Queue.prototype,{indexOf:function(t){return e.Array.indexOf(this._q,t)},promote:function(e){var t=this.indexOf(e);t>-1&&this._q.unshift(this._q.splice(t,1)[0])},remove:function(e){var t=this.indexOf(e);t>-1&&this._q.splice(t,1)}})},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/range-slider/assets/slider-base-core.css b/js/yui3/range-slider/assets/slider-base-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/range-slider/assets/slider-base-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/range-slider/assets/slider-core.css b/js/yui3/range-slider/assets/slider-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/range-slider/assets/slider-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/range-slider/assets/thumb-x-oblong-dark.png b/js/yui3/range-slider/assets/thumb-x-oblong-dark.png
new file mode 100644
index 000000000..bc0aa14ce
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-x-oblong-dark.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-x-oblong.png b/js/yui3/range-slider/assets/thumb-x-oblong.png
new file mode 100644
index 000000000..670ba1ea1
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-x-oblong.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-x-oblong2-dark.png b/js/yui3/range-slider/assets/thumb-x-oblong2-dark.png
new file mode 100644
index 000000000..20f126029
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-x-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-x-oblong2.png b/js/yui3/range-slider/assets/thumb-x-oblong2.png
new file mode 100644
index 000000000..76e34e60a
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-x-oblong2.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-y-oblong-dark.png b/js/yui3/range-slider/assets/thumb-y-oblong-dark.png
new file mode 100644
index 000000000..a0eed7087
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-y-oblong-dark.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-y-oblong.png b/js/yui3/range-slider/assets/thumb-y-oblong.png
new file mode 100644
index 000000000..e63c8d7d8
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-y-oblong.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-y-oblong2-dark.png b/js/yui3/range-slider/assets/thumb-y-oblong2-dark.png
new file mode 100644
index 000000000..e91ffb7b3
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-y-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/range-slider/assets/thumb-y-oblong2.png b/js/yui3/range-slider/assets/thumb-y-oblong2.png
new file mode 100644
index 000000000..89a466727
--- /dev/null
+++ b/js/yui3/range-slider/assets/thumb-y-oblong2.png
Binary files differ
diff --git a/js/yui3/range-slider/range-slider-min.js b/js/yui3/range-slider/range-slider-min.js
new file mode 100644
index 000000000..27ab4b175
--- /dev/null
+++ b/js/yui3/range-slider/range-slider-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("range-slider",function(e,t){e.Slider=e.Base.build("slider",e.SliderBase,[e.SliderValueRange,e.ClickableRail])},"3.7.3",{requires:["slider-base","slider-value-range","clickable-rail"]});
diff --git a/js/yui3/recordset-base/recordset-base-min.js b/js/yui3/recordset-base/recordset-base-min.js
new file mode 100644
index 000000000..a5435eb63
--- /dev/null
+++ b/js/yui3/recordset-base/recordset-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("recordset-base",function(e,t){var n=e.Base.create("record",e.Base,[],{_setId:function(){return e.guid()},initializer:function(){},destructor:function(){},getValue:function(e){return e===undefined?this.get("data"):this.get("data")[e]}},{ATTRS:{id:{valueFn:"_setId"},data:{value:null}}});e.Record=n;var r=e.ArrayList,i=e.Lang,s=e.Base.create("recordset",e.Base,[],{initializer:function(){this._items||(this._items=[]),this.publish({add:{defaultFn:this._defAddFn},remove:{defaultFn:this._defRemoveFn},empty:{defaultFn:this._defEmptyFn},update:{defaultFn:this._defUpdateFn}}),this._buildHashTable(this.get("key")),this.after(["recordsChange","add","remove","update","empty"],this._updateHash)},getRecord:function(e){return i.isString(e)?this.get("table")[e]:i.isNumber(e)?this._items[e]:null},getRecordByIndex:function(e){return this._items[e]},getRecordsByIndex:function(e,t){var n=0,r=[];t=i.isNumber(t)&&t>0?t:1;for(;n<t;n++)r.push(this._items[e+n]);return r},getLength:function(){return this.size()},getValuesByKey:function(e){var t=0,n=this._items.length,r=[];for(;t<n;t++)r.push(this._items[t].getValue(e));return r},add:function(e,t){var n=[],r,s=0;r=i.isNumber(t)&&t>-1?t:this._items.length;if(i.isArray(e))for(;s<e.length;s++)n[s]=this._changeToRecord(e[s]);else i.isObject(e)&&(n[0]=this._changeToRecord(e));return this.fire("add",{added:n,index:r}),this},remove:function(e,t){var n=[];return e=e>-1?e:this._items.length-1,t=t>0?t:1,n=this._items.slice(e,e+t),this.fire("remove",{removed:n,range:t,index:e}),this},empty:function(){return this.fire("empty",{}),this},update:function(e,t){var n,r,s=0;r=i.isArray(e)?e:[e],n=this._items.slice(t,t+r.length);for(;s<r.length;s++)r[s]=this._changeToRecord(r[s]);return this.fire("update",{updated:r,overwritten:n,index:t}),this},_defAddFn:function(e){this._items.splice.apply(this._items,[e.index,0].concat(e.added))},_defRemoveFn:function(e){this._items.splice(e.index,e.range||1)},_defUpdateFn:function(e){for(var t=0;t<e.updated.length;t++)this._items[e.index+t]=this._changeToRecord(e.updated[t])},_defEmptyFn:function(e){this._items=[]},_updateHash:function(e){var t="_hash",n=e.type.replace(/.*:/,""),r;t+=n.charAt(0).toUpperCase()+n.slice(1),r=this[t]&&this[t](this.get("table"),this.get("key"),e),r&&this.set("table",r)},_hashRecordsChange:function(e,t,n){return this._buildHashTable(t)},_buildHashTable:function(e){return this._hashAdd({},e,{added:this._items})},_hashAdd:function(e,t,n){var r=n.added,i,s;for(i=0,s=n.added.length;i<s;++i)e[r[i].get(t)]=r[i];return e},_hashRemove:function(e,t,n){for(var r=n.removed.length-1;r>=0;--r)delete e[n.removed[r].get(t)];return e},_hashUpdate:function(e,t,n){return n.overwritten&&n.overwritten.length&&(e=this._hashRemove(e,t,{removed:n.overwritten})),this._hashAdd(e,t,{added:n.updated})},_hashEmpty:function(){return{}},_initHashTable:function(){return this._hashAdd({},this.get("key"),{added:this._items||[]})},_changeToRecord:function(t){return t instanceof e.Record?t:new e.Record({data:t})},_setRecords:function(t){if(!e.Lang.isArray(t))return e.Attribute.INVALID_VALUE;var n=[],r,i;for(r=0,i=t.length;r<i;++r)n[r]=this._changeToRecord(t[r]);return this._items=n}},{ATTRS:{records:{lazyAdd:!1,getter:function(){return e.Array(this._items)},setter:"_setRecords"},table:{valueFn:"_initHashTable"},key:{value:"id",readOnly:!0}}});e.augment(s,r),e.Recordset=s},"3.7.3",{requires:["base","arraylist"]});
diff --git a/js/yui3/recordset-filter/recordset-filter-min.js b/js/yui3/recordset-filter/recordset-filter-min.js
new file mode 100644
index 000000000..6f4c005cb
--- /dev/null
+++ b/js/yui3/recordset-filter/recordset-filter-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("recordset-filter",function(e,t){function i(e){i.superclass.constructor.apply(this,arguments)}var n=e.Array,r=e.Lang;e.mix(i,{NS:"filter",NAME:"recordsetFilter",ATTRS:{}}),e.extend(i,e.Plugin.Base,{filter:function(t,i){var s=this.get("host").get("records"),o;return i&&r.isString(t)&&(o=t,t=function(e){return e.getValue(o)===i}),new e.Recordset({records:n.filter(s,t)})},reject:function(t){return new e.Recordset({records:n.reject(this.get("host").get("records"),t)})},grep:function(t){return new e.Recordset({records:n.grep(this.get("host").get("records"),t)})}}),e.namespace("Plugin").RecordsetFilter=i},"3.7.3",{requires:["recordset-base","array-extras","plugin"]});
diff --git a/js/yui3/recordset-indexer/recordset-indexer-min.js b/js/yui3/recordset-indexer/recordset-indexer-min.js
new file mode 100644
index 000000000..b00e48c6c
--- /dev/null
+++ b/js/yui3/recordset-indexer/recordset-indexer-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("recordset-indexer",function(e,t){function n(e){n.superclass.constructor.apply(this,arguments)}e.mix(n,{NS:"indexer",NAME:"recordsetIndexer",ATTRS:{hashTables:{value:{}},keys:{value:{}}}}),e.extend(n,e.Plugin.Base,{initializer:function(t){var n=this.get("host");this.onHostEvent("add",e.bind("_defAddHash",this),n),this.onHostEvent("remove",e.bind("_defRemoveHash",this),n),this.onHostEvent("update",e.bind("_defUpdateHash",this),n)},destructor:function(e){},_setHashTable:function(e){var t=this.get("host"),n={},r=0,i=t.getLength();for(;r<i;r++)n[t._items[r].getValue(e)]=t._items[r];return n},_defAddHash:function(t){var n=this.get("hashTables");e.each(n,function(n,r){e.each(t.added||t.updated,function(e){e.getValue(r)&&(n[e.getValue(r)]=e)})})},_defRemoveHash:function(t){var n=this.get("hashTables"),r;e.each(n,function(n,i){e.each(t.removed||t.overwritten,function(e){r=e.getValue(i),r&&n[r]===e&&delete n[r]})})},_defUpdateHash:function(e){e.added=e.updated,e.removed=e.overwritten,this._defAddHash(e),this._defRemoveHash(e)},createTable:function(e){var t=this.get("hashTables");return t[e]=this._setHashTable(e),this.set("hashTables",t),t[e]},getTable:function(e){return this.get("hashTables")[e]}}),e.namespace("Plugin").RecordsetIndexer=n},"3.7.3",{requires:["recordset-base","plugin"]});
diff --git a/js/yui3/recordset-sort/recordset-sort-min.js b/js/yui3/recordset-sort/recordset-sort-min.js
new file mode 100644
index 000000000..6286443fd
--- /dev/null
+++ b/js/yui3/recordset-sort/recordset-sort-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("recordset-sort",function(e,t){function i(e,t,n){i.superclass.constructor.apply(this,arguments)}var n=e.ArraySort.compare,r=e.Lang.isValue;e.mix(i,{NS:"sort",NAME:"recordsetSort",ATTRS:{lastSortProperties:{value:{field:undefined,desc:!0,sorter:undefined},validator:function(e){return r(e.field)&&r(e.desc)&&r(e.sorter)}},defaultSorter:{value:function(e,t,r,i){var s=n(e.getValue(r),t.getValue(r),i);return s===0?n(e.get("id"),t.get("id"),i):s}},isSorted:{value:!1}}}),e.extend(i,e.Plugin.Base,{initializer:function(t){var n=this,r=this.get("host");this.publish("sort",{defaultFn:e.bind("_defSortFn",this)}),this.on("sort",function(){n.set("isSorted",!0)}),this.onHostEvent("add",function(){n.set("isSorted",!1)},r),this.onHostEvent("update",function(){n.set("isSorted",!1)},r)},destructor:function(e){},_defSortFn:function(e){this.get("host")._items.sort(function(t,n){return e.sorter(t,n,e.field,e.desc)}),this.set("lastSortProperties",e)},sort:function(e,t,n){this.fire("sort",{field:e,desc:t,sorter:n||this.get("defaultSorter")})},resort:function(){var e=this.get("lastSortProperties");this.fire("sort",{field:e.field,desc:e.desc,sorter:e.sorter||this.get("defaultSorter")})},reverse:function(){this.get("host")._items.reverse()},flip:function(){var e=this.get("lastSortProperties");r(e.field)&&this.fire("sort",{field:e.field,desc:!e.desc,sorter:e.sorter||this.get("defaultSorter")})}}),e.namespace("Plugin").RecordsetSort=i},"3.7.3",{requires:["arraysort","recordset-base","plugin"]});
diff --git a/js/yui3/resize-base/assets/resize-base-core.css b/js/yui3/resize-base/assets/resize-base-core.css
new file mode 100644
index 000000000..5b4676972
--- /dev/null
+++ b/js/yui3/resize-base/assets/resize-base-core.css
@@ -0,0 +1,247 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper {
+ z-index: 0;
+ zoom: 1;
+}
+
+.yui3-resize-handle {
+ position: absolute;
+ display: block;
+ z-index: 100;
+ zoom: 1;
+}
+
+.yui3-resize-proxy {
+ position: absolute;
+ border: 1px dashed #000;
+ position: absolute;
+ z-index: 10000;
+}
+
+.yui3-resize-hidden-handles .yui3-resize-handle {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+
+.yui3-resize-handle-t,
+.yui3-resize-handle-b {
+ width: 100%;
+ left: 0;
+ height: 6px;
+}
+
+.yui3-resize-handle-l,
+.yui3-resize-handle-r {
+ height: 100%;
+ top: 0;
+ width: 6px;
+}
+
+.yui3-resize-handle-t {
+ cursor: n-resize;
+ top: 0;
+}
+
+.yui3-resize-handle-b {
+ cursor: s-resize;
+ bottom: 0;
+}
+
+.yui3-resize-handle-l {
+ cursor: w-resize;
+ left: 0;
+}
+
+.yui3-resize-handle-r {
+ cursor: e-resize;
+ right: 0;
+}
+
+.yui3-resize-handle-inner {
+ position: absolute;
+ zoom: 1;
+}
+
+/* Smartphones (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 320px)
+and (max-device-width : 480px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -12px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -12px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+/* iPads (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 768px)
+and (max-device-width : 1024px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -6px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -6px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b {
+ margin-left: -8px;
+ left: 50%;
+}
+
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-r {
+ margin-top: -8px;
+ top: 50%;
+}
+
+.yui3-resize-handle-inner-t {
+ top: -4px;
+}
+
+.yui3-resize-handle-inner-b {
+ bottom: -4px;
+}
+
+.yui3-resize-handle-inner-l {
+ left: -4px;
+}
+
+.yui3-resize-handle-inner-r {
+ right: -4px;
+}
+
+.yui3-resize-handle-tr,
+.yui3-resize-handle-br,
+.yui3-resize-handle-tl,
+.yui3-resize-handle-bl {
+ height: 15px;
+ width: 15px;
+ z-index: 200;
+}
+
+.yui3-resize-handle-tr {
+ cursor: ne-resize;
+ top: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-tl {
+ cursor: nw-resize;
+ top: 0;
+ left: 0;
+}
+
+.yui3-resize-handle-br {
+ cursor: se-resize;
+ bottom: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-bl {
+ cursor: sw-resize;
+ bottom: 0;
+ left: 0;
+} \ No newline at end of file
diff --git a/js/yui3/resize-base/assets/skins/night/arrows.png b/js/yui3/resize-base/assets/skins/night/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-base/assets/skins/night/arrows.png
Binary files differ
diff --git a/js/yui3/resize-base/assets/skins/night/resize-base.css b/js/yui3/resize-base/assets/skins/night/resize-base.css
new file mode 100644
index 000000000..1a0ada2e8
--- /dev/null
+++ b/js/yui3/resize-base/assets/skins/night/resize-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper{z-index:0;zoom:1}.yui3-resize-handle{position:absolute;display:block;z-index:100;zoom:1}.yui3-resize-proxy{position:absolute;border:1px dashed #000;position:absolute;z-index:10000}.yui3-resize-hidden-handles .yui3-resize-handle{opacity:0;filter:alpha(opacity=0)}.yui3-resize-handle-t,.yui3-resize-handle-b{width:100%;left:0;height:6px}.yui3-resize-handle-l,.yui3-resize-handle-r{height:100%;top:0;width:6px}.yui3-resize-handle-t{cursor:n-resize;top:0}.yui3-resize-handle-b{cursor:s-resize;bottom:0}.yui3-resize-handle-l{cursor:w-resize;left:0}.yui3-resize-handle-r{cursor:e-resize;right:0}.yui3-resize-handle-inner{position:absolute;zoom:1}@media only screen and (min-device-width :320px) and (max-device-width:480px){.yui3-resize-handle-inner:after{content:"";width:40px;height:40px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-12px;right:0}.yui3-resize-handle-inner-l:after{top:-12px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-12px}.yui3-resize-handle-inner-b:after{bottom:0;left:-12px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}@media only screen and (min-device-width :768px) and (max-device-width:1024px){.yui3-resize-handle-inner:after{content:"";width:30px;height:30px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-6px;right:0}.yui3-resize-handle-inner-l:after{top:-6px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-6px}.yui3-resize-handle-inner-b:after{bottom:0;left:-6px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b{margin-left:-8px;left:50%}.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-r{margin-top:-8px;top:50%}.yui3-resize-handle-inner-t{top:-4px}.yui3-resize-handle-inner-b{bottom:-4px}.yui3-resize-handle-inner-l{left:-4px}.yui3-resize-handle-inner-r{right:-4px}.yui3-resize-handle-tr,.yui3-resize-handle-br,.yui3-resize-handle-tl,.yui3-resize-handle-bl{height:15px;width:15px;z-index:200}.yui3-resize-handle-tr{cursor:ne-resize;top:0;right:0}.yui3-resize-handle-tl{cursor:nw-resize;top:0;left:0}.yui3-resize-handle-br{cursor:se-resize;bottom:0;right:0}.yui3-resize-handle-bl{cursor:sw-resize;bottom:0;left:0}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{background-repeat:no-repeat;background:url(arrows.png) no-repeat 0 0;display:block;height:15px;overflow:hidden;text-indent:-99999em;width:15px}.yui3-resize-handle-inner-br{background-position:-30px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tr{background-position:-58px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-bl{background-position:-75px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tl{background-position:-47px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t{background-position:-15px 0}#yui3-css-stamp.skin-night-resize-base{display:none}
diff --git a/js/yui3/resize-base/assets/skins/sam/arrows.png b/js/yui3/resize-base/assets/skins/sam/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-base/assets/skins/sam/arrows.png
Binary files differ
diff --git a/js/yui3/resize-base/assets/skins/sam/resize-base.css b/js/yui3/resize-base/assets/skins/sam/resize-base.css
new file mode 100644
index 000000000..e915ab263
--- /dev/null
+++ b/js/yui3/resize-base/assets/skins/sam/resize-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper{z-index:0;zoom:1}.yui3-resize-handle{position:absolute;display:block;z-index:100;zoom:1}.yui3-resize-proxy{position:absolute;border:1px dashed #000;position:absolute;z-index:10000}.yui3-resize-hidden-handles .yui3-resize-handle{opacity:0;filter:alpha(opacity=0)}.yui3-resize-handle-t,.yui3-resize-handle-b{width:100%;left:0;height:6px}.yui3-resize-handle-l,.yui3-resize-handle-r{height:100%;top:0;width:6px}.yui3-resize-handle-t{cursor:n-resize;top:0}.yui3-resize-handle-b{cursor:s-resize;bottom:0}.yui3-resize-handle-l{cursor:w-resize;left:0}.yui3-resize-handle-r{cursor:e-resize;right:0}.yui3-resize-handle-inner{position:absolute;zoom:1}@media only screen and (min-device-width :320px) and (max-device-width:480px){.yui3-resize-handle-inner:after{content:"";width:40px;height:40px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-12px;right:0}.yui3-resize-handle-inner-l:after{top:-12px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-12px}.yui3-resize-handle-inner-b:after{bottom:0;left:-12px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}@media only screen and (min-device-width :768px) and (max-device-width:1024px){.yui3-resize-handle-inner:after{content:"";width:30px;height:30px;position:absolute}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{overflow:visible!important}.yui3-resize-handle-inner-r:after{top:-6px;right:0}.yui3-resize-handle-inner-l:after{top:-6px;left:0}.yui3-resize-handle-inner-t:after{top:0;left:-6px}.yui3-resize-handle-inner-b:after{bottom:0;left:-6px}.yui3-resize-handle-inner-tr:after{top:0;right:0}.yui3-resize-handle-inner-br:after{bottom:0;right:0}.yui3-resize-handle-inner-tl:after{top:0;left:0}.yui3-resize-handle-inner-bl:after{bottom:0;left:0}}.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b{margin-left:-8px;left:50%}.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-r{margin-top:-8px;top:50%}.yui3-resize-handle-inner-t{top:-4px}.yui3-resize-handle-inner-b{bottom:-4px}.yui3-resize-handle-inner-l{left:-4px}.yui3-resize-handle-inner-r{right:-4px}.yui3-resize-handle-tr,.yui3-resize-handle-br,.yui3-resize-handle-tl,.yui3-resize-handle-bl{height:15px;width:15px;z-index:200}.yui3-resize-handle-tr{cursor:ne-resize;top:0;right:0}.yui3-resize-handle-tl{cursor:nw-resize;top:0;left:0}.yui3-resize-handle-br{cursor:se-resize;bottom:0;right:0}.yui3-resize-handle-bl{cursor:sw-resize;bottom:0;left:0}.yui3-resize-handle-inner-r,.yui3-resize-handle-inner-l,.yui3-resize-handle-inner-t,.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-tr,.yui3-resize-handle-inner-br,.yui3-resize-handle-inner-tl,.yui3-resize-handle-inner-bl{background-repeat:no-repeat;background:url(arrows.png) no-repeat 0 0;display:block;height:15px;overflow:hidden;text-indent:-99999em;width:15px}.yui3-resize-handle-inner-br{background-position:-30px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tr{background-position:-58px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-bl{background-position:-75px 0;bottom:-2px;right:-2px}.yui3-resize-handle-inner-tl{background-position:-47px 0;bottom:0;right:-2px}.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t{background-position:-15px 0}#yui3-css-stamp.skin-sam-resize-base{display:none}
diff --git a/js/yui3/resize-base/resize-base-min.js b/js/yui3/resize-base/resize-base-min.js
new file mode 100644
index 000000000..084e1b399
--- /dev/null
+++ b/js/yui3/resize-base/resize-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("resize-base",function(e,t){function Lt(){Lt.superclass.constructor.apply(this,arguments)}var n=e.Lang,r=n.isArray,i=n.isBoolean,s=n.isNumber,o=n.isString,u=e.Array,a=n.trim,f=u.indexOf,l=",",c=".",h="",p="{handle}",d=" ",v="active",m="activeHandle",g="activeHandleNode",y="all",b="autoHide",w="border",E="bottom",S="className",x="color",T="defMinHeight",N="defMinWidth",C="handle",k="handles",L="handlesWrapper",A="hidden",O="inner",M="left",_="margin",D="node",P="nodeName",H="none",B="offsetHeight",j="offsetWidth",F="padding",I="parentNode",q="position",R="relative",U="resize",z="resizing",W="right",X="static",V="style",$="top",J="width",K="wrap",Q="wrapper",G="wrapTypes",Y="resize:mouseUp",Z="resize:resize",et="resize:align",tt="resize:end",nt="resize:start",rt="t",it="tr",st="r",ot="br",ut="b",at="bl",ft="l",lt="tl",ct=function(){return Array.prototype.slice.call(arguments).join(d)},ht=function(e){return Math.round(parseFloat(e))||0},pt=function(e,t){return e.getComputedStyle(t)},dt=function(e){return C+e.toUpperCase()},vt=function(t){return t instanceof e.Node},mt=e.cached(function(e){return e.substring(0,1).toUpperCase()+e.substring(1)}),gt=e.cached(function(){var e=[],t=u(arguments,0,!0);return u.each(t,function(t,n){n>0&&(t=mt(t)),e.push(t)}),e.join(h)}),yt=e.ClassNameManager.getClassName,bt=yt(U),wt=yt(U,C),Et=yt(U,C,v),St=yt(U,C,O),xt=yt(U,C,O,p),Tt=yt(U,C,p),Nt=yt(U,A,k),Ct=yt(U,k,Q),kt=yt(U,Q);e.mix(Lt,{NAME:U,ATTRS:{activeHandle:{value:null,validator:function(t){return e.Lang.isString(t)||e.Lang.isNull(t)}},activeHandleNode:{value:null,validator:vt},autoHide:{value:!1,validator:i},defMinHeight:{value:15,validator:s},defMinWidth:{value:15,validator:s},handles:{setter:"_setHandles",value:y},handlesWrapper:{readOnly:!0,setter:e.one,valueFn:"_valueHandlesWrapper"},node:{setter:e.one},resizing:{value:!1,validator:i},wrap:{setter:"_setWrap",value:!1,validator:i},wrapTypes:{readOnly:!0,value:/^canvas|textarea|input|select|button|img|iframe|table|embed$/i},wrapper:{readOnly:!0,valueFn:"_valueWrapper",writeOnce:!0}},RULES:{b:function(e,t,n){var r=e.info,i=e.originalInfo;r.offsetHeight=i.offsetHeight+n},l:function(e,t){var n=e.info,r=e.originalInfo;n.left=r.left+t,n.offsetWidth=r.offsetWidth-t},r:function(e,t){var n=e.info,r=e.originalInfo;n.offsetWidth=r.offsetWidth+t},t:function(e,t,n){var r=e.info,i=e.originalInfo;r.top=i.top+n,r.offsetHeight=i.offsetHeight-n},tr:function(){this.t.apply(this,arguments),this.r.apply(this,arguments)},bl:function(){this.b.apply(this,arguments),this.l.apply(this,arguments)},br:function(){this.b.apply(this,arguments),this.r.apply(this,arguments)},tl:function(){this.t.apply(this,arguments),this.l.apply(this,arguments)}},capitalize:gt}),e.Resize=e.extend(Lt,e.Base,{ALL_HANDLES:[rt,it,st,ot,ut,at,ft,lt],REGEX_CHANGE_HEIGHT:/^(t|tr|b|bl|br|tl)$/i,REGEX_CHANGE_LEFT:/^(tl|l|bl)$/i,REGEX_CHANGE_TOP:/^(tl|t|tr)$/i,REGEX_CHANGE_WIDTH:/^(bl|br|l|r|tl|tr)$/i,HANDLES_WRAP_TEMPLATE:'<div class="'+Ct+'"></div>',WRAP_TEMPLATE:'<div class="'+kt+'"></div>',HANDLE_TEMPLATE:'<div class="'+ct(wt,Tt)+'">'+'<div class="'+ct(St,xt)+'">&nbsp;</div>'+"</div>",totalHSurrounding:0,totalVSurrounding:0,nodeSurrounding:null,wrapperSurrounding:null,changeHeightHandles:!1,changeLeftHandles:!1,changeTopHandles:!1,changeWidthHandles:!1,delegate:null,info:null,lastInfo:null,originalInfo:null,initializer:function(){this._eventHandles=[],this.renderer()},renderUI:function(){var e=this;e._renderHandles()},bindUI:function(){var e=this;e._createEvents(),e._bindDD(),e._bindHandle()},syncUI:function(){var e=this;this.get(D).addClass(bt),e._setHideHandlesUI(e.get(b))},destructor:function(){var t=this,n=t.get(D),r=t.get(Q),i=r.get(I);e.each(t._eventHandles,function(e){e.detach()}),t._eventHandles.length=0,t.eachHandle(function(e){t.delegate.dd.destroy(),e.remove(!0)}),t.delegate.destroy(),t.get(K)&&(t._copyStyles(r,n),i&&i.insertBefore(n,r),r.remove(!0)),n.removeClass(bt),n.removeClass(Nt)},renderer:function(){this.renderUI(),this.bindUI(),this.syncUI()},eachHandle:function(t){var n=this;e.each(n.get(k),function(e,r){var i=n.get(dt(e));t.apply(n,[i,e,r])})},_bindDD:function(){var t=this;t.delegate=new e.DD.Delegate({bubbleTargets:t,container:t.get(L),dragConfig:{clickPixelThresh:0,clickTimeThresh:0,useShim:!0,move:!1},nodes:c+wt,target:!1}),t._eventHandles.push(t.on("drag:drag",t._handleResizeEvent),t.on("drag:dropmiss",t._handleMouseUpEvent),t.on("drag:end",t._handleResizeEndEvent),t.on("drag:start",t._handleResizeStartEvent))},_bindHandle:function(){var t=this,n=t.get(Q);t._eventHandles.push(n.on("mouseenter",e.bind(t._onWrapperMouseEnter,t)),n.on("mouseleave",e.bind(t._onWrapperMouseLeave,t)),n.delegate("mouseenter",e.bind(t._onHandleMouseEnter,t),c+wt),n.delegate("mouseleave",e.bind(t._onHandleMouseLeave,t),c+wt))},_createEvents:function(){var e=this,t=function(t,n){e.publish(t,{defaultFn:n,queuable:!1,emitFacade:!0,bubbles:!0,prefix:U})};t(nt,this._defResizeStartFn),t(Z,this._defResizeFn),t(et,this._defResizeAlignFn),t(tt,this._defResizeEndFn),t(Y,this._defMouseUpFn)},_renderHandles:function(){var e=this,t=e.get(Q),n=e.get(L);e.eachHandle(function(e){n.append(e)}),t.append(n)},_buildHandle:function(t){var n=this;return e.Node.create(e.Lang.sub(n.HANDLE_TEMPLATE,{handle:t}))},_calcResize:function(){var t=this,n=t.handle,r=t.info,i=t.originalInfo,s=r.actXY[0]-i.actXY[0],o=r.actXY[1]-i.actXY[1];n&&e.Resize.RULES[n]&&e.Resize.RULES[n](t,s,o)},_checkSize:function(e,t){var n=this,r=n.info,i=n.originalInfo,s=e===B?$:M;r[e]=t;if(s===M&&n.changeLeftHandles||s===$&&n.changeTopHandles)r[s]=i[s]+i[e]-t},_copyStyles:function(t,n){var r=t.getStyle(q).toLowerCase(),i=this._getBoxSurroundingInfo(t),s;r===X&&(r=R),s={position:r,left:pt(t,M),top:pt(t,$)},e.mix(s,i.margin),e.mix(s,i.border),n.setStyles(s),t.setStyles({border:0,margin:0}),n.sizeTo(t.get(j)+i.totalHBorder,t.get(B)+i.totalVBorder)},_extractHandleName:e.cached(function(e){var t=e.get(S),n=t.match(new RegExp(yt(U,C,"(\\w{1,2})\\b")));return n?n[1]:null}),_getInfo:function(e,t){var n=[0,0],r=t.dragEvent.target,i=e.getXY(),s=i[0],o=i[1],u=e.get(B),a=e.get(j);return t&&(n=r.actXY.length?r.actXY:r.lastXY),{actXY:n,bottom:o+u,left:s,offsetHeight:u,offsetWidth:a,right:s+a,top:o}},_getBoxSurroundingInfo:function(t){var n={padding:{},margin:{},border:{}};return vt(t)&&e.each([$,W,E,M],function(e){var r=gt(F,e),i=gt(_,e),s=gt(w,e,J),o=gt(w,e,x),u=gt(w,e,V);n.border[o]=pt(t,o),n.border[u]=pt(t,u),n.border[s]=pt(t,s),n.margin[i]=pt(t,i),n.padding[r]=pt(t,r)}),n.totalHBorder=ht(n.border.borderLeftWidth)+ht(n.border.borderRightWidth),n.totalHPadding=ht(n.padding.paddingLeft)+ht(n.padding.paddingRight),n.totalVBorder=ht(n.border.borderBottomWidth)+ht(n.border.borderTopWidth),n.totalVPadding=ht(n.padding.paddingBottom)+ht(n.padding.paddingTop),n},_syncUI:function(){var t=this,n=t.info,r=t.wrapperSurrounding,i=t.get(Q),s=t.get(D);i.sizeTo(n.offsetWidth,n.offsetHeight),(t.changeLeftHandles||t.changeTopHandles)&&i.setXY([n.left,n.top]),i.compareTo(s)||s.sizeTo(n.offsetWidth-r.totalHBorder,n.offsetHeight-r.totalVBorder),e.UA.webkit&&s.setStyle(U,H)},_updateChangeHandleInfo:function(e){var t=this;t.changeHeightHandles=t.REGEX_CHANGE_HEIGHT.test(e),t.changeLeftHandles=t.REGEX_CHANGE_LEFT.test(e),t.changeTopHandles=t.REGEX_CHANGE_TOP.test(e),t.changeWidthHandles=t.REGEX_CHANGE_WIDTH.test(e)},_updateInfo:function(e){var t=this;t.info=t._getInfo(t.get(Q),e)},_updateSurroundingInfo:function(){var e=this,t=e.get(D),n=e.get(Q),r=e._getBoxSurroundingInfo(t),i=e._getBoxSurroundingInfo(n);e.nodeSurrounding=r,e.wrapperSurrounding=i,e.totalVSurrounding=r.totalVPadding+i.totalVBorder,e.totalHSurrounding=r.totalHPadding+i.totalHBorder},_setActiveHandlesUI:function(e){var t=this,n=t.get(g);n&&(e?(t.eachHandle(function(e){e.removeClass(Et)}),n.addClass(Et)):n.removeClass(Et))},_setHandles:function(t){var n=this,i=[];return r(t)?i=t:o(t)&&(t.toLowerCase()===y?i=n.ALL_HANDLES:e.each(t.split(l),function(e){var t=a(e);f(n.ALL_HANDLES,t)>-1&&i.push(t)})),i},_setHideHandlesUI:function(e){var t=this,n=t.get(Q);t.get(z)||(e?n.addClass(Nt):n.removeClass(Nt))},_setWrap:function(e){var t=this,n=t.get(D),r=n.get(P),i=t.get(G);return i.test(r)&&(e=!0),e},_defMouseUpFn:function(){var e=this;e.set(z,!1)},_defResizeFn:function(e){var t=this;t._resize(e)},_resize:function(e){var t=this;t._handleResizeAlignEvent(e.dragEvent),t._syncUI()},_defResizeAlignFn:function(e){var t=this;t._resizeAlign(e)},_resizeAlign:function(e){var t=this,n,r,i;t.lastInfo=t.info,t._updateInfo(e),n=t.info,t._calcResize(),t.con||(r=t.get(T)+t.totalVSurrounding,i=t.get(N)+t.totalHSurrounding,n.offsetHeight<=r&&t._checkSize(B,r),n.offsetWidth<=i&&t._checkSize(j,i))},_defResizeEndFn:function(e){var t=this;t._resizeEnd(e)},_resizeEnd:function(e){var t=this,n=e.dragEvent.target;n.actXY=[],t._syncUI(),t._setActiveHandlesUI(!1),t.set(m,null),t.set(g,null),t.handle=null},_defResizeStartFn:function(e){var t=this;t._resizeStart(e)},_resizeStart:function(e){var t=this,n=t.get(Q);t.handle=t.get(m),t.set(z,!0),t._updateSurroundingInfo(),t.originalInfo=t._getInfo(n,e),t._updateInfo(e)},_handleMouseUpEvent:function(e){this.fire(Y,{dragEvent:e,info:this.info})},_handleResizeEvent:function(e){this.fire(Z,{dragEvent:e,info:this.info})},_handleResizeAlignEvent:function(e){this.fire(et,{dragEvent:e,info:this.info})},_handleResizeEndEvent:function(e){this.fire(tt,{dragEvent:e,info:this.info})},_handleResizeStartEvent:function(e){this.get(m)||this._setHandleFromNode(e.target.get("node")),this.fire(nt,{dragEvent:e,info:this.info})},_onWrapperMouseEnter:function(){var e=this;e.get(b)&&e._setHideHandlesUI(!1)},_onWrapperMouseLeave:function(){var e=this;e.get(b)&&e._setHideHandlesUI(!0)},_setHandleFromNode:function(e){var t=this,n=t._extractHandleName(e);t.get(z)||(t.set(m,n),t.set(g,e),t._setActiveHandlesUI(!0),t._updateChangeHandleInfo(n))},_onHandleMouseEnter:function(e){this._setHandleFromNode(e.currentTarget)},_onHandleMouseLeave:function(){var e=this;e.get(z)||e._setActiveHandlesUI(!1)},_valueHandlesWrapper:function(){return e.Node.create(this.HANDLES_WRAP_TEMPLATE)},_valueWrapper:function(){var t=this,n=t.get(D),r=n.get(I),i=n;return t.get(K)&&(i=e.Node.create(t.WRAP_TEMPLATE),r&&r.insertBefore(i,n),i.append(n),t._copyStyles(n,i),n.setStyles({position:X,left:0,top:0})),i}}),e.each(e.Resize.prototype.ALL_HANDLES,function(t){e.Resize.ATTRS[dt(t)]={setter:function(){return this._buildHandle(t)},value:null,writeOnce:!0}})},"3.7.3",{requires:["base","widget","event","oop","dd-drag","dd-delegate","dd-drop"],skinnable:!0});
diff --git a/js/yui3/resize-constrain/assets/resize-base-core.css b/js/yui3/resize-constrain/assets/resize-base-core.css
new file mode 100644
index 000000000..5b4676972
--- /dev/null
+++ b/js/yui3/resize-constrain/assets/resize-base-core.css
@@ -0,0 +1,247 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper {
+ z-index: 0;
+ zoom: 1;
+}
+
+.yui3-resize-handle {
+ position: absolute;
+ display: block;
+ z-index: 100;
+ zoom: 1;
+}
+
+.yui3-resize-proxy {
+ position: absolute;
+ border: 1px dashed #000;
+ position: absolute;
+ z-index: 10000;
+}
+
+.yui3-resize-hidden-handles .yui3-resize-handle {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+
+.yui3-resize-handle-t,
+.yui3-resize-handle-b {
+ width: 100%;
+ left: 0;
+ height: 6px;
+}
+
+.yui3-resize-handle-l,
+.yui3-resize-handle-r {
+ height: 100%;
+ top: 0;
+ width: 6px;
+}
+
+.yui3-resize-handle-t {
+ cursor: n-resize;
+ top: 0;
+}
+
+.yui3-resize-handle-b {
+ cursor: s-resize;
+ bottom: 0;
+}
+
+.yui3-resize-handle-l {
+ cursor: w-resize;
+ left: 0;
+}
+
+.yui3-resize-handle-r {
+ cursor: e-resize;
+ right: 0;
+}
+
+.yui3-resize-handle-inner {
+ position: absolute;
+ zoom: 1;
+}
+
+/* Smartphones (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 320px)
+and (max-device-width : 480px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -12px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -12px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+/* iPads (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 768px)
+and (max-device-width : 1024px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -6px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -6px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b {
+ margin-left: -8px;
+ left: 50%;
+}
+
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-r {
+ margin-top: -8px;
+ top: 50%;
+}
+
+.yui3-resize-handle-inner-t {
+ top: -4px;
+}
+
+.yui3-resize-handle-inner-b {
+ bottom: -4px;
+}
+
+.yui3-resize-handle-inner-l {
+ left: -4px;
+}
+
+.yui3-resize-handle-inner-r {
+ right: -4px;
+}
+
+.yui3-resize-handle-tr,
+.yui3-resize-handle-br,
+.yui3-resize-handle-tl,
+.yui3-resize-handle-bl {
+ height: 15px;
+ width: 15px;
+ z-index: 200;
+}
+
+.yui3-resize-handle-tr {
+ cursor: ne-resize;
+ top: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-tl {
+ cursor: nw-resize;
+ top: 0;
+ left: 0;
+}
+
+.yui3-resize-handle-br {
+ cursor: se-resize;
+ bottom: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-bl {
+ cursor: sw-resize;
+ bottom: 0;
+ left: 0;
+} \ No newline at end of file
diff --git a/js/yui3/resize-constrain/assets/skins/night/arrows.png b/js/yui3/resize-constrain/assets/skins/night/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-constrain/assets/skins/night/arrows.png
Binary files differ
diff --git a/js/yui3/resize-constrain/assets/skins/night/resize-base-skin.css b/js/yui3/resize-constrain/assets/skins/night/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-constrain/assets/skins/night/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-constrain/assets/skins/sam/arrows.png b/js/yui3/resize-constrain/assets/skins/sam/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-constrain/assets/skins/sam/arrows.png
Binary files differ
diff --git a/js/yui3/resize-constrain/assets/skins/sam/resize-base-skin.css b/js/yui3/resize-constrain/assets/skins/sam/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-constrain/assets/skins/sam/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-constrain/resize-constrain-min.js b/js/yui3/resize-constrain/resize-constrain-min.js
new file mode 100644
index 000000000..17506052a
--- /dev/null
+++ b/js/yui3/resize-constrain/resize-constrain-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("resize-constrain",function(e,t){function B(){B.superclass.constructor.apply(this,arguments)}var n=e.Lang,r=n.isBoolean,i=n.isNumber,s=n.isString,o=e.Resize.capitalize,u=function(t){return t instanceof e.Node},a=function(e){return parseFloat(e)||0},f="borderBottomWidth",l="borderLeftWidth",c="borderRightWidth",h="borderTopWidth",p="border",d="bottom",v="con",m="constrain",g="host",y="left",b="maxHeight",w="maxWidth",E="minHeight",S="minWidth",x="node",T="offsetHeight",N="offsetWidth",C="preserveRatio",k="region",L="resizeConstrained",A="right",O="tickX",M="tickY",_="top",D="width",P="view",H="viewportRegion";e.mix(B,{NAME:L,NS:v,ATTRS:{constrain:{setter:function(t){return t&&(u(t)||s(t)||t.nodeType)&&(t=e.one(t)),t}},minHeight:{value:15,validator:i},minWidth:{value:15,validator:i},maxHeight:{value:Infinity,validator:i},maxWidth:{value:Infinity,validator:i},preserveRatio:{value:!1,validator:r},tickX:{value:!1},tickY:{value:!1}}}),e.extend(B,e.Plugin.Base,{constrainSurrounding:null,initializer:function(){var t=this,n=t.get(g);n.delegate.dd.plug(e.Plugin.DDConstrained,{tickX:t.get(O),tickY:t.get(M)}),n.after("resize:align",e.bind(t._handleResizeAlignEvent,t)),n.on("resize:start",e.bind(t._handleResizeStartEvent,t))},_checkConstrain:function(e,t,n){var r=this,i,s,u,f,l=r.get(g),c=l.info,h=r.constrainSurrounding.border,d=r._getConstrainRegion();d&&(i=c[e]+c[n],s=d[t]-a(h[o(p,t,D)]),i>=s&&(c[n]-=i-s),u=c[e],f=d[e]+a(h[o(p,e,D)]),u<=f&&(c[e]+=f-u,c[n]-=f-u))},_checkHeight:function(){var e=this,t=e.get(g),n=t.info,r=e.get(b)+t.totalVSurrounding,i=e.get(E)+t.totalVSurrounding;e._checkConstrain(_,d,T),n.offsetHeight>r&&t._checkSize(T,r),n.offsetHeight<i&&t._checkSize(T,i)},_checkRatio:function(){var t=this,n=t.get(g),r=n.info,s=n.originalInfo,o=s.offsetWidth,u=s.offsetHeight,p=s.top,d=s.left,v=s.bottom,y=s.right,b=function(){return r.offsetWidth/o},w=function(){return r.offsetHeight/u},E=n.changeHeightHandles,S,x,T,N,C,k;t.get(m)&&n.changeHeightHandles&&n.changeWidthHandles&&(T=t._getConstrainRegion(),x=t.constrainSurrounding.border,S=T.bottom-a(x[f])-v,N=d-(T.left+a(x[l])),C=T.right-a(x[c])-y,k=p-(T.top+a(x[h])),n.changeLeftHandles&&n.changeTopHandles?E=k<N:n.changeLeftHandles?E=S<N:n.changeTopHandles?E=k<C:E=S<C),E?(r.offsetWidth=o*w(),t._checkWidth(),r.offsetHeight=u*b()):(r.offsetHeight=u*b(),t._checkHeight(),r.offsetWidth=o*w()),n.changeTopHandles&&(r.top=p+(u-r.offsetHeight)),n.changeLeftHandles&&(r.left=d+(o-r.offsetWidth)),e.each(r,function(e,t){i(e)&&(r[t]=Math.round(e))})},_checkRegion:function(){var t=this,n=t.get(g),r=t._getConstrainRegion();return e.DOM.inRegion(null,r,!0,n.info)},_checkWidth:function(){var e=this,t=e.get(g),n=t.info,r=e.get(w)+t.totalHSurrounding,i=e.get(S)+t.totalHSurrounding;e._checkConstrain(y,A,N),n.offsetWidth<i&&t._checkSize(N,i),n.offsetWidth>r&&t._checkSize(N,r)},_getConstrainRegion:function(){var e=this,t=e.get(g),n=t.get(x),r=e.get(m),i=null;return r&&(r===P?i=n.get(H):u(r)?i=r.get(k):i=r),i},_handleResizeAlignEvent:function(){var e=this,t=e.get(g);e._checkHeight(),e._checkWidth(),e.get(C)&&e._checkRatio(),e.get(m)&&!e._checkRegion()&&(t.info=t.lastInfo)},_handleResizeStartEvent:function(){var e=this,t=e.get(m),n=e.get(g);e.constrainSurrounding=n._getBoxSurroundingInfo(t)}}),e.namespace("Plugin"),e.Plugin.ResizeConstrained=B},"3.7.3",{requires:["plugin","resize-base"]});
diff --git a/js/yui3/resize-plugin/assets/resize-base-core.css b/js/yui3/resize-plugin/assets/resize-base-core.css
new file mode 100644
index 000000000..5b4676972
--- /dev/null
+++ b/js/yui3/resize-plugin/assets/resize-base-core.css
@@ -0,0 +1,247 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper {
+ z-index: 0;
+ zoom: 1;
+}
+
+.yui3-resize-handle {
+ position: absolute;
+ display: block;
+ z-index: 100;
+ zoom: 1;
+}
+
+.yui3-resize-proxy {
+ position: absolute;
+ border: 1px dashed #000;
+ position: absolute;
+ z-index: 10000;
+}
+
+.yui3-resize-hidden-handles .yui3-resize-handle {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+
+.yui3-resize-handle-t,
+.yui3-resize-handle-b {
+ width: 100%;
+ left: 0;
+ height: 6px;
+}
+
+.yui3-resize-handle-l,
+.yui3-resize-handle-r {
+ height: 100%;
+ top: 0;
+ width: 6px;
+}
+
+.yui3-resize-handle-t {
+ cursor: n-resize;
+ top: 0;
+}
+
+.yui3-resize-handle-b {
+ cursor: s-resize;
+ bottom: 0;
+}
+
+.yui3-resize-handle-l {
+ cursor: w-resize;
+ left: 0;
+}
+
+.yui3-resize-handle-r {
+ cursor: e-resize;
+ right: 0;
+}
+
+.yui3-resize-handle-inner {
+ position: absolute;
+ zoom: 1;
+}
+
+/* Smartphones (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 320px)
+and (max-device-width : 480px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -12px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -12px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+/* iPads (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 768px)
+and (max-device-width : 1024px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -6px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -6px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b {
+ margin-left: -8px;
+ left: 50%;
+}
+
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-r {
+ margin-top: -8px;
+ top: 50%;
+}
+
+.yui3-resize-handle-inner-t {
+ top: -4px;
+}
+
+.yui3-resize-handle-inner-b {
+ bottom: -4px;
+}
+
+.yui3-resize-handle-inner-l {
+ left: -4px;
+}
+
+.yui3-resize-handle-inner-r {
+ right: -4px;
+}
+
+.yui3-resize-handle-tr,
+.yui3-resize-handle-br,
+.yui3-resize-handle-tl,
+.yui3-resize-handle-bl {
+ height: 15px;
+ width: 15px;
+ z-index: 200;
+}
+
+.yui3-resize-handle-tr {
+ cursor: ne-resize;
+ top: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-tl {
+ cursor: nw-resize;
+ top: 0;
+ left: 0;
+}
+
+.yui3-resize-handle-br {
+ cursor: se-resize;
+ bottom: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-bl {
+ cursor: sw-resize;
+ bottom: 0;
+ left: 0;
+} \ No newline at end of file
diff --git a/js/yui3/resize-plugin/assets/skins/night/arrows.png b/js/yui3/resize-plugin/assets/skins/night/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-plugin/assets/skins/night/arrows.png
Binary files differ
diff --git a/js/yui3/resize-plugin/assets/skins/night/resize-base-skin.css b/js/yui3/resize-plugin/assets/skins/night/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-plugin/assets/skins/night/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-plugin/assets/skins/sam/arrows.png b/js/yui3/resize-plugin/assets/skins/sam/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-plugin/assets/skins/sam/arrows.png
Binary files differ
diff --git a/js/yui3/resize-plugin/assets/skins/sam/resize-base-skin.css b/js/yui3/resize-plugin/assets/skins/sam/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-plugin/assets/skins/sam/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-plugin/resize-plugin-min.js b/js/yui3/resize-plugin/resize-plugin-min.js
new file mode 100644
index 000000000..f8cd8b076
--- /dev/null
+++ b/js/yui3/resize-plugin/resize-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("resize-plugin",function(e,t){var n=function(t){t.node=e.Widget&&t.host instanceof e.Widget?t.host.get("boundingBox"):t.host,t.host instanceof e.Widget?t.widget=t.host:t.widget=!1,n.superclass.constructor.call(this,t)};n.NAME="resize-plugin",n.NS="resize",n.ATTRS={node:{value:undefined},widget:{value:undefined}},e.extend(n,e.Resize,{initializer:function(e){this.set("node",e.node),this.set("widget",e.widget),this.on("resize:resize",function(e){this._correctDimensions(e)})},_correctDimensions:function(e){var t=this.get("node"),n={old:t.getX(),cur:e.currentTarget.info.left},r={old:t.getY(),cur:e.currentTarget.info.top};this.get("widget")&&this._setWidgetProperties(e,n,r),this._isDifferent(n.old,n.cur)&&t.set("x",n.cur),this._isDifferent(r.old,r.cur)&&t.set("y",r.cur)},_setWidgetProperties:function(t,n,r){var i=this.get("widget"),s=i.get("height"),o=i.get("width"),u=t.currentTarget.info.offsetWidth-t.currentTarget.totalHSurrounding,a=t.currentTarget.info.offsetHeight-t.currentTarget.totalVSurrounding;this._isDifferent(s,a)&&i.set("height",a),this._isDifferent(o,u)&&i.set("width",u),i.hasImpl&&i.hasImpl(e.WidgetPosition)&&(this._isDifferent(i.get("x"),n.cur)&&i.set("x",n.cur),this._isDifferent(i.get("y"),r.cur)&&i.set("y",r.cur))},_isDifferent:function(e,t){var n=!1;return e!==t&&(n=t),n}}),e.namespace("Plugin"),e.Plugin.Resize=n},"3.7.3",{requires:["resize-base","plugin"],optional:["resize-constrain"]});
diff --git a/js/yui3/resize-proxy/assets/resize-base-core.css b/js/yui3/resize-proxy/assets/resize-base-core.css
new file mode 100644
index 000000000..5b4676972
--- /dev/null
+++ b/js/yui3/resize-proxy/assets/resize-base-core.css
@@ -0,0 +1,247 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize,.yui3-resize-wrapper {
+ z-index: 0;
+ zoom: 1;
+}
+
+.yui3-resize-handle {
+ position: absolute;
+ display: block;
+ z-index: 100;
+ zoom: 1;
+}
+
+.yui3-resize-proxy {
+ position: absolute;
+ border: 1px dashed #000;
+ position: absolute;
+ z-index: 10000;
+}
+
+.yui3-resize-hidden-handles .yui3-resize-handle {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+
+.yui3-resize-handle-t,
+.yui3-resize-handle-b {
+ width: 100%;
+ left: 0;
+ height: 6px;
+}
+
+.yui3-resize-handle-l,
+.yui3-resize-handle-r {
+ height: 100%;
+ top: 0;
+ width: 6px;
+}
+
+.yui3-resize-handle-t {
+ cursor: n-resize;
+ top: 0;
+}
+
+.yui3-resize-handle-b {
+ cursor: s-resize;
+ bottom: 0;
+}
+
+.yui3-resize-handle-l {
+ cursor: w-resize;
+ left: 0;
+}
+
+.yui3-resize-handle-r {
+ cursor: e-resize;
+ right: 0;
+}
+
+.yui3-resize-handle-inner {
+ position: absolute;
+ zoom: 1;
+}
+
+/* Smartphones (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 320px)
+and (max-device-width : 480px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -12px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -12px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -12px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+/* iPads (portrait and landscape) -----------
+Adding larger hit-area ':after' objects to handles
+*/
+@media only screen
+and (min-device-width : 768px)
+and (max-device-width : 1024px) {
+/* Styles */
+ .yui3-resize-handle-inner:after {
+ content: "";
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ }
+
+ .yui3-resize-handle-inner-r,
+ .yui3-resize-handle-inner-l,
+ .yui3-resize-handle-inner-t,
+ .yui3-resize-handle-inner-b,
+ .yui3-resize-handle-inner-tr,
+ .yui3-resize-handle-inner-br,
+ .yui3-resize-handle-inner-tl,
+ .yui3-resize-handle-inner-bl {
+ overflow: visible !important;
+ }
+
+ .yui3-resize-handle-inner-r:after {
+ top: -6px;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-l:after {
+ top: -6px;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-t:after {
+ top: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-b:after {
+ bottom: 0;
+ left: -6px;
+ }
+ .yui3-resize-handle-inner-tr:after {
+ top: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-br:after {
+ bottom: 0;
+ right: 0;
+ }
+ .yui3-resize-handle-inner-tl:after {
+ top: 0;
+ left: 0;
+ }
+ .yui3-resize-handle-inner-bl:after {
+ bottom: 0;
+ left: 0;
+ }
+}
+
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b {
+ margin-left: -8px;
+ left: 50%;
+}
+
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-r {
+ margin-top: -8px;
+ top: 50%;
+}
+
+.yui3-resize-handle-inner-t {
+ top: -4px;
+}
+
+.yui3-resize-handle-inner-b {
+ bottom: -4px;
+}
+
+.yui3-resize-handle-inner-l {
+ left: -4px;
+}
+
+.yui3-resize-handle-inner-r {
+ right: -4px;
+}
+
+.yui3-resize-handle-tr,
+.yui3-resize-handle-br,
+.yui3-resize-handle-tl,
+.yui3-resize-handle-bl {
+ height: 15px;
+ width: 15px;
+ z-index: 200;
+}
+
+.yui3-resize-handle-tr {
+ cursor: ne-resize;
+ top: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-tl {
+ cursor: nw-resize;
+ top: 0;
+ left: 0;
+}
+
+.yui3-resize-handle-br {
+ cursor: se-resize;
+ bottom: 0;
+ right: 0;
+}
+
+.yui3-resize-handle-bl {
+ cursor: sw-resize;
+ bottom: 0;
+ left: 0;
+} \ No newline at end of file
diff --git a/js/yui3/resize-proxy/assets/skins/night/arrows.png b/js/yui3/resize-proxy/assets/skins/night/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-proxy/assets/skins/night/arrows.png
Binary files differ
diff --git a/js/yui3/resize-proxy/assets/skins/night/resize-base-skin.css b/js/yui3/resize-proxy/assets/skins/night/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-proxy/assets/skins/night/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-proxy/assets/skins/sam/arrows.png b/js/yui3/resize-proxy/assets/skins/sam/arrows.png
new file mode 100644
index 000000000..2942681f4
--- /dev/null
+++ b/js/yui3/resize-proxy/assets/skins/sam/arrows.png
Binary files differ
diff --git a/js/yui3/resize-proxy/assets/skins/sam/resize-base-skin.css b/js/yui3/resize-proxy/assets/skins/sam/resize-base-skin.css
new file mode 100644
index 000000000..e0af10d6b
--- /dev/null
+++ b/js/yui3/resize-proxy/assets/skins/sam/resize-base-skin.css
@@ -0,0 +1,52 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-resize-handle-inner-r,
+.yui3-resize-handle-inner-l,
+.yui3-resize-handle-inner-t,
+.yui3-resize-handle-inner-b,
+.yui3-resize-handle-inner-tr,
+.yui3-resize-handle-inner-br,
+.yui3-resize-handle-inner-tl,
+.yui3-resize-handle-inner-bl {
+ background-repeat: no-repeat;
+ background: url(arrows.png) no-repeat 0 0;
+ display: block;
+ height: 15px;
+ overflow: hidden;
+ text-indent: -99999em;
+ width: 15px;
+}
+
+.yui3-resize-handle-inner-br {
+ background-position: -30px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tr {
+ background-position: -58px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-bl {
+ background-position: -75px 0;
+ bottom: -2px;
+ right: -2px;
+}
+
+.yui3-resize-handle-inner-tl {
+ background-position: -47px 0;
+ bottom: 0;
+ right: -2px;
+
+}
+
+.yui3-resize-handle-inner-b,.yui3-resize-handle-inner-t {
+ background-position: -15px 0;
+}
diff --git a/js/yui3/resize-proxy/resize-proxy-min.js b/js/yui3/resize-proxy/resize-proxy-min.js
new file mode 100644
index 000000000..009faee8d
--- /dev/null
+++ b/js/yui3/resize-proxy/resize-proxy-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("resize-proxy",function(e,t){function d(){d.superclass.constructor.apply(this,arguments)}var n="activeHandleNode",r="cursor",i="dragCursor",s="host",o="parentNode",u="proxy",a="proxyNode",f="resize",l="resize-proxy",c="wrapper",h=e.ClassNameManager.getClassName,p=h(f,u);e.mix(d,{NAME:l,NS:u,ATTRS:{proxyNode:{setter:e.one,valueFn:function(){return e.Node.create(this.PROXY_TEMPLATE)}}}}),e.extend(d,e.Plugin.Base,{PROXY_TEMPLATE:'<div class="'+p+'"></div>',initializer:function(){var e=this;e.afterHostEvent("resize:start",e._afterResizeStart),e.beforeHostMethod("_resize",e._beforeHostResize),e.afterHostMethod("_resizeEnd",e._afterHostResizeEnd)},destructor:function(){var e=this;e.get(a).remove(!0)},_afterHostResizeEnd:function(e){var t=this,n=e.dragEvent.target;n.actXY=[],t._syncProxyUI(),t.get(a).hide()},_afterResizeStart:function(){var e=this;e._renderProxy()},_beforeHostResize:function(t){var n=this,r=this.get(s);return r._handleResizeAlignEvent(t.dragEvent),n._syncProxyUI(),new e.Do.Prevent},_renderProxy:function(){var e=this,t=this.get(s),n=e.get(a);n.inDoc()||t.get(c).get(o).append(n.hide())},_syncProxyUI:function(){var e=this,t=this.get(s),o=t.info,u=t.get(n),f=e.get(a),l=u.getStyle(r);f.show().setStyle(r,l),t.delegate.dd.set(i,l),f.sizeTo(o.offsetWidth,o.offsetHeight),f.setXY([o.left,o.top])}}),e.namespace("Plugin"),e.Plugin.ResizeProxy=d},"3.7.3",{requires:["plugin","resize-base"]});
diff --git a/js/yui3/router/router-min.js b/js/yui3/router/router-min.js
new file mode 100644
index 000000000..cf2f00e08
--- /dev/null
+++ b/js/yui3/router/router-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("router",function(e,t){function l(){l.superclass.constructor.apply(this,arguments)}var n=e.HistoryHash,r=e.QueryString,i=e.Array,s=e.Lang,o=e.config.win,u=[],a=[],f="ready";e.Router=e.extend(l,e.Base,{_regexPathParam:/([:*])([\w\-]+)?/g,_regexUrlQuery:/\?([^#]*).*$/,_regexUrlOrigin:/^(?:[^\/#?:]+:\/\/|\/\/)[^\/]*/,initializer:function(t){var n=this;n._html5=n.get("html5"),n._routes=[],n._url=n._getURL(),n._setRoutes(t&&t.routes?t.routes:n.get("routes")),n._html5?(n._history=new e.HistoryHTML5({force:!0}),n._historyEvents=e.after("history:change",n._afterHistoryChange,n)):n._historyEvents=e.on("hashchange",n._afterHistoryChange,o,n),n.publish(f,{defaultFn:n._defReadyFn,fireOnce:!0,preventable:!1}),n.once("initializedChange",function(){e.once("load",function(){setTimeout(function(){n.fire(f,{dispatched:!!n._dispatched})},20)})}),u.push(this)},destructor:function(){var e=i.indexOf(u,this);e>-1&&u.splice(e,1),this._historyEvents&&this._historyEvents.detach()},dispatch:function(){return this.once(f,function(){this._ready=!0;if(this._html5&&this.upgrade())return;this._dispatch(this._getPath(),this._getURL())}),this},getPath:function(){return this._getPath()},hasRoute:function(e){var t;return this._hasSameOrigin(e)?(this._html5||(e=this._upgradeURL(e)),t=this.removeQuery(this.removeRoot(e)),!!this.match(t).length):!1},match:function(e){return i.filter(this._routes,function(t){return e.search(t.regex)>-1})},removeRoot:function(e){var t=this.get("root");return e=e.replace(this._regexUrlOrigin,""),t&&e.indexOf(t)===0&&(e=e.substring(t.length)),e.charAt(0)==="/"?e:"/"+e},removeQuery:function(e){return e.replace(/\?.*$/,"")},replace:function(e){return this._queue(e,!0)},route:function(e,t){t=i.flatten(i(arguments,1,!0));var n=[];return this._routes.push({callbacks:t,keys:n,path:e,regex:this._getRegex(e,n),callback:t[0]}),this},save:function(e){return this._queue(e)},upgrade:function(){if(!this._html5)return!1;var e=this._getHashPath();return e?(this.once(f,function(){this.replace(e)}),!0):!1},_decode:function(e){return decodeURIComponent(e.replace(/\+/g," "))},_dequeue:function(){var t=this,n;return YUI.Env.windowLoaded?(n=a.shift(),n?n():this):(e.once("load",function(){t._dequeue()}),this)},_dispatch:function(t,n,r){var s=this,o=s.match(t),u=[],a,f,l;return s._dispatching=s._dispatched=!0,!o||!o.length?(s._dispatching=!1,s):(f=s._getRequest(t,n,r),l=s._getResponse(f),f.next=function(n){var r,c;if(n)n==="route"?(u=[],f.next()):e.error(n);else if(r=u.shift())typeof r=="string"&&(r=s[r]),f.pendingCallbacks=u.length,r.call(s,f,l,f.next);else if(c=o.shift())u=c.callbacks.concat(),a=c.regex.exec(t),a.length===c.keys.length+1?f.params=i.hash(c.keys,a.slice(1)):f.params=a.concat(),f.pendingRoutes=o.length,f.next()},f.next(),s._dispatching=!1,s._dequeue())},_getHashPath:function(e){return e||(e=n.getHash()),e&&e.charAt(0)==="/"?this._joinURL(e):""},_getOrigin:function(){var t=e.getLocation();return t.origin||t.protocol+"//"+t.host},_getPath:function(){var t=!this._html5&&this._getHashPath()||e.getLocation().pathname;return this.removeQuery(this.removeRoot(t))},_getPathRoot:function(){var t="/",n=e.getLocation().pathname,r;return n.charAt(n.length-1)===t?n:(r=n.split(t),r.pop(),r.join(t)+t)},_getQuery:function(){var t=e.getLocation(),r,i;return this._html5?t.search.substring(1):(r=n.getHash(),i=r.match(this._regexUrlQuery),r&&i?i[1]:t.search.substring(1))},_getRegex:function(e,t){return e instanceof RegExp?e:e==="*"?/.*/:(e=e.replace(this._regexPathParam,function(e,n,r){return r?(t.push(r),n==="*"?"(.*?)":"([^/#?]*)"):n==="*"?".*":e}),new RegExp("^"+e+"$"))},_getRequest:function(e,t,n){return{path:e,query:this._parseQuery(this._getQuery()),url:t,src:n}},_getResponse:function(e){var t=function(){return e.next.apply(this,arguments)};return t.req=e,t},_getRoutes:function(){return this._routes.concat()},_getURL:function(){var t=e.getLocation().toString();return this._html5||(t=this._upgradeURL(t)),t},_hasSameOrigin:function(t){var n=(t&&t.match(this._regexUrlOrigin)||[])[0];return n&&n.indexOf("//")===0&&(n=e.getLocation().protocol+n),!n||n===this._getOrigin()},_joinURL:function(e){var t=this.get("root");return e=this.removeRoot(e),e.charAt(0)==="/"&&(e=e.substring(1)),t&&t.charAt(t.length-1)==="/"?t+e:t+"/"+e},_normalizePath:function(e){var t="..",n="/",r,i,s,o,u,a;if(!e||e===n)return n;o=e.split(n),a=[];for(r=0,i=o.length;r<i;++r)u=o[r],u===t?a.pop():u&&a.push(u);return s=n+a.join(n),s!==n&&e.charAt(e.length-1)===n&&(s+=n),s},_parseQuery:r&&r.parse?r.parse:function(e){var t=this._decode,n=e.split("&"),r=0,i=n.length,s={},o;for(;r<i;++r)o=n[r].split("="),o[0]&&(s[t(o[0])]=t(o[1]||""));return s},_queue:function(){var t=arguments,n=this;return a.push(function(){return n._html5?e.UA.ios&&e.UA.ios<5?n._save.apply(n,t):setTimeout(function(){n._save.apply(n,t)},1):(n._dispatching=!0,n._save.apply(n,t)),n}),this._dispatching?this:this._dequeue()},_resolvePath:function(t){return t?(t.charAt(0)!=="/"&&(t=this._getPathRoot()+t),this._normalizePath(t)):e.getLocation().pathname},_resolveURL:function(t){var n=t&&t.match(this._regexURL),r,i,s,o,u;return n?(r=n[1],i=n[2],s=n[3],o=n[4],r?(r.indexOf("//")===0&&(r=e.getLocation().protocol+r),r+(i||"/")+(s||"")+(o||"")):(u=this._getOrigin()+this._resolvePath(i),i||s?u+(s||"")+(o||""):(s=this._getQuery(),u+(s?"?"+s:"")+(o||"")))):e.getLocation().toString()},_save:function(t,r){var i=typeof t=="string",s,o;if(i&&!this._hasSameOrigin(t))return e.error("Security error: The new URL must be of the same origin as the current URL."),this;i&&(t=this._joinURL(t)),this._ready=!0;if(this._html5)this._history[r?"replace":"add"](null,{url:t});else{s=e.getLocation().pathname,o=this.get("root");if(o===s||o===this._getPathRoot())t=this.removeRoot(t);t===n.getHash()?e.Router.dispatch():n[r?"replaceHash":"setHash"](t)}return this},_setRoutes:function(e){return this._routes=[],i.each(e,function(e){var t=e.callbacks||e.callback;this.route(e.path,t)},this),this._routes.concat()},_upgradeURL:function(t){if(!this._hasSameOrigin(t))return t;var n=(t.match(/#(.*)$/)||[])[1]||"",r=e.HistoryHash.hashPrefix,i;return r&&n.indexOf(r)===0&&(n=n.replace(r,"")),n&&(i=this._getHashPath(n)),i?this._resolveURL(i):t},_afterHistoryChange:function(e){var t=this,n=e.src,r=t._url,i=t._getURL();t._url=i;if(n==="popstate"&&(!t._ready||r.replace(/#.*$/,"")===i.replace(/#.*$/,"")))return;t._dispatch(t._getPath(),i,n)},_defReadyFn:function(e){this._ready=!0}},{NAME:"router",ATTRS:{html5:{valueFn:function(){return e.Router.html5},writeOnce:"initOnly"},root:{value:""},routes:{value:[],getter:"_getRoutes",setter:"_setRoutes"}},html5:e.HistoryBase.html5&&(!e.UA.android||e.UA.android>=3),_instances:u,dispatch:function(){var e,t,n;for(e=0,t=u.length;e<t;e+=1)n=u[e],n&&n._dispatch(n._getPath(),n._getURL())}}),e.Controller=e.Router},"3.7.3",{optional:["querystring-parse"],requires:["array-extras","base-build","history"]});
diff --git a/js/yui3/scrollview-base-ie/scrollview-base-ie-min.js b/js/yui3/scrollview-base-ie/scrollview-base-ie-min.js
new file mode 100644
index 000000000..eba1cc430
--- /dev/null
+++ b/js/yui3/scrollview-base-ie/scrollview-base-ie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview-base-ie",function(e,t){e.mix(e.ScrollView.prototype,{_fixIESelect:function(t,n){this._cbDoc=n.get("ownerDocument"),this._nativeBody=e.Node.getDOMNode(e.one("body",this._cbDoc)),n.on("mousedown",function(){this._selectstart=this._nativeBody.onselectstart,this._nativeBody.onselectstart=this._iePreventSelect,this._cbDoc.once("mouseup",this._ieRestoreSelect,this)},this)},_iePreventSelect:function(){return!1},_ieRestoreSelect:function(){this._nativeBody.onselectstart=this._selectstart}},!0)},"3.7.3",{requires:["scrollview-base"]});
diff --git a/js/yui3/scrollview-base/assets/scrollview-base-core.css b/js/yui3/scrollview-base/assets/scrollview-base-core.css
new file mode 100644
index 000000000..507f5987a
--- /dev/null
+++ b/js/yui3/scrollview-base/assets/scrollview-base-core.css
@@ -0,0 +1,20 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview {
+ position: relative;
+ overflow: hidden;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+}
+
+.yui3-scrollview-hidden {
+ display:none;
+}
+
+.yui3-scrollview-content {
+ position:relative;
+} \ No newline at end of file
diff --git a/js/yui3/scrollview-base/assets/skins/night/scrollview-base.css b/js/yui3/scrollview-base/assets/skins/night/scrollview-base.css
new file mode 100644
index 000000000..2c2a35952
--- /dev/null
+++ b/js/yui3/scrollview-base/assets/skins/night/scrollview-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none}.yui3-scrollview-hidden{display:none}.yui3-scrollview-content{position:relative}#yui3-css-stamp.skin-night-scrollview-base{display:none}
diff --git a/js/yui3/scrollview-base/assets/skins/sam/scrollview-base.css b/js/yui3/scrollview-base/assets/skins/sam/scrollview-base.css
new file mode 100644
index 000000000..15ea4d0aa
--- /dev/null
+++ b/js/yui3/scrollview-base/assets/skins/sam/scrollview-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none}.yui3-scrollview-hidden{display:none}.yui3-scrollview-content{position:relative}.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}#yui3-css-stamp.skin-sam-scrollview-base{display:none}
diff --git a/js/yui3/scrollview-base/scrollview-base-min.js b/js/yui3/scrollview-base/scrollview-base-min.js
new file mode 100644
index 000000000..61e676712
--- /dev/null
+++ b/js/yui3/scrollview-base/scrollview-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview-base",function(e,t){function R(){R.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r=e.config.doc,i=e.config.win,s=e.UA.ie,o=e.Transition.useNative,u=e.Transition._VENDOR_PREFIX,a="scrollview",f={vertical:n(a,"vert"),horizontal:n(a,"horiz")},l="scrollEnd",c="flick",h="drag",p="mousewheel",d="ui",v="top",m="right",g="bottom",y="left",b="px",w="axis",E="scrollY",S="scrollX",x="bounce",T="disabled",N="deceleration",C="x",k="y",L="boundingBox",A="contentBox",O="gesturemove",M="start",_="end",D="",P="0s",H="snapDuration",B="snapEasing",j="easing",F="frameDuration",I="bounceRange",q=function(e,t,n){return Math.min(Math.max(e,t),n)};e.ScrollView=e.extend(R,e.Widget,{_forceHWTransforms:e.UA.webkit?!0:!1,_prevent:{start:!1,move:!0,end:!1},lastScrolledAmt:0,initializer:function(e){var t=this;t._bb=t.get(L),t._cb=t.get(A),t._cAxis=t.get(w),t._cBounce=t.get(x),t._cBounceRange=t.get(I),t._cDeceleration=t.get(N),t._cFrameDuration=t.get(F)},bindUI:function(){var e=this;e._bindFlick(e.get(c)),e._bindDrag(e.get(h)),e._bindMousewheel(!0),e._bindAttrs(),s&&e._fixIESelect(e._bb,e._cb),R.SNAP_DURATION&&e.set(H,R.SNAP_DURATION),R.SNAP_EASING&&e.set(B,R.SNAP_EASING),R.EASING&&e.set(j,R.EASING),R.FRAME_STEP&&e.set(F,R.FRAME_STEP),R.BOUNCE_RANGE&&e.set(I,R.BOUNCE_RANGE)},_bindAttrs:function(){var e=this,t=e._afterScrollChange,n=e._afterDimChange;e.after({scrollEnd:e._afterScrollEnd,disabledChange:e._afterDisabledChange,flickChange:e._afterFlickChange,dragChange:e._afterDragChange,axisChange:e._afterAxisChange,scrollYChange:t,scrollXChange:t,heightChange:n,widthChange:n})},_bindDrag:function(t){var n=this,r=n._bb;r.detach(h+"|*"),t&&r.on(h+"|"+O+M,e.bind(n._onGestureMoveStart,n))},_bindFlick:function(t){var n=this,r=n._bb;r.detach(c+"|*"),t&&(r.on(c+"|"+c,e.bind(n._flick,n),t),n._bindDrag(n.get(h)))},_bindMousewheel:function(t){var n=this,i=n._bb;i.detach(p+"|*"),t&&e.one(r).on(p,e.bind(n._mousewheel,n))},syncUI:function(){var e=this,t=e._getScrollDims(),n=t.offsetWidth,r=t.offsetHeight,i=t.scrollWidth,s=t.scrollHeight;e._cAxis===undefined&&(e._cAxis={x:i>n,y:s>r},e._set(w,e._cAxis)),e.rtl=e._cb.getComputedStyle("direction")==="rtl",e._cDisabled=e.get(T),e._uiDimensionsChange(),e._isOutOfBounds()&&e._snapBack()},_getScrollDims:function(){var e=this,t=e._cb,n=e._bb,r=R._TRANSITION,i=e.get(S),s=e.get(E),u,a;return o&&(t.setStyle(r.DURATION,P),t.setStyle(r.PROPERTY,D)),u=e._forceHWTransforms,e._forceHWTransforms=!1,e._moveTo(t,0,0),a={offsetWidth:n.get("offsetWidth"),offsetHeight:n.get("offsetHeight"),scrollWidth:n.get("scrollWidth"),scrollHeight:n.get("scrollHeight")},e._moveTo(t,-i,-s),e._forceHWTransforms=u,a},_uiDimensionsChange:function(){var e=this,t=e._bb,n=e._getScrollDims(),r=n.offsetWidth,i=n.offsetHeight,s=n.scrollWidth,o=n.scrollHeight,u=e.rtl,a=e._cAxis;a&&a.x&&t.addClass(f.horizontal),a&&a.y&&t.addClass(f.vertical),e._minScrollX=u?Math.min(0,-(s-r)):0,e._maxScrollX=u?0:Math.max(0,s-r),e._minScrollY=0,e._maxScrollY=Math.max(0,o-i)},scrollTo:function(t,n,r,i,s){if(this._cDisabled)return;var u=this,a=u._cb,f=R._TRANSITION,l=e.bind(u._onTransEnd,u),c=0,h=0,p={},m;r=r||0,i=i||u.get(j),s=s||a,t!==null&&(u.set(S,t,{src:d}),c=-t),n!==null&&(u.set(E,n,{src:d}),h=-n),m=u._transform(c,h),o&&s.setStyle(f.DURATION,P).setStyle(f.PROPERTY,D),r===0?o?s.setStyle("transform",m):(t!==null&&s.setStyle(y,c+b),n!==null&&s.setStyle(v,h+b)):(p.easing=i,p.duration=r/1e3,o?p.transform=m:(p.left=c+b,p.top=h+b),s.transition(p,l))},_transform:function(e,t){var n="translate("+e+"px, "+t+"px)";return this._forceHWTransforms&&(n+=" translateZ(0)"),n},_moveTo:function(e,t,n){o?e.setStyle("transform",this._transform(t,n)):(e.setStyle(y,t+b),e.setStyle(v,n+b))},_onTransEnd:function(e){var t=this;t.fire(l)},_onGestureMoveStart:function(t){if(this._cDisabled)return!1;var n=this,r=n._bb,i=n.get(S),s=n.get(E),o=t.clientX,u=t.clientY;n._prevent.start&&t.preventDefault(),n._flickAnim&&(n._flickAnim.cancel(),delete n._flickAnim,n._onTransEnd()),t.stopPropagation(),n.lastScrolledAmt=0,n._gesture={axis:null,startX:i,startY:s,startClientX:o,startClientY:u,endClientX:null,endClientY:null,deltaX:null,deltaY:null,flick:null,onGestureMove:r.on(h+"|"+O,e.bind(n._onGestureMove,n)),onGestureMoveEnd:r.on(h+"|"+O+_,e.bind(n._onGestureMoveEnd,n))}},_onGestureMove:function(e){var t=this,n=t._gesture,r=t._cAxis,i=r.x,s=r.y,o=n.startX,u=n.startY,a=n.startClientX,f=n.startClientY,l=e.clientX,c=e.clientY;t._prevent.move&&e.preventDefault(),n.deltaX=a-l,n.deltaY=f-c,n.axis===null&&(n.axis=Math.abs(n.deltaX)>Math.abs(n.deltaY)?C:k),n.axis===C&&i?t.set(S,o+n.deltaX):n.axis===k&&s&&t.set(E,u+n.deltaY)},_onGestureMoveEnd:function(e){var t=this,n=t._gesture,r=n.flick,i=e.clientX,s=e.clientY;t._prevent.end&&e.preventDefault(),n.endClientX=i,n.endClientY=s,n.onGestureMove.detach(),n.onGestureMoveEnd.detach(),r||n.deltaX!==null&&n.deltaY!==null&&(t._isOutOfBounds()?t._snapBack():t.pages&&!t.pages.get(w)[n.axis]&&t._onTransEnd())},_flick:function(e){if(this._cDisabled)return!1;var t=this,n=t._cAxis,r=e.flick,i=r.axis,s=r.velocity,o=i===C?S:E,u=t.get(o);t._gesture&&(t._gesture.flick=r),n[i]&&t._flickFrame(s,i,u)},_flickFrame:function(t,n,r){var i=this,s=n===C?S:E,o=i._cBounce,u=i._cBounceRange,a=i._cDeceleration,f=i._cFrameDuration,l=t*a,c=r-f*l,h=n===C?i._minScrollX:i._minScrollY,p=n===C?i._maxScrollX:i._maxScrollY,d=c<h,v=c<p,m=c>h,g=c>p,y=c<h-u,b=c<p+u,w=d&&c>h-u,x=g&&c<p+u,T=c>h-u,N=c>p+u,k;if(w||x)l*=o;k=Math.abs(l).toFixed(4)<.015,k||y||N?(i._flickAnim&&(i._flickAnim.cancel(),delete i._flickAnim),m&&v?i._onTransEnd():i._snapBack()):(i._flickAnim=e.later(f,i,"_flickFrame",[l,n,c]),i.set(s,c))},_mousewheel:function(e){var t=this,n=t.get(E),r=t._bb,i=10,s=e.wheelDelta>0,o=n-(s?1:-1)*i;o=q(o,t._minScrollY,t._maxScrollY),r.contains(e.target)&&t._cAxis[k]&&(t.lastScrolledAmt=0,t.set(E,o),t.scrollbars&&(t.scrollbars._update(),t.scrollbars.flash()),t._onTransEnd(),e.preventDefault())},_isOutOfBounds:function(e,t){var n=this,r=n._cAxis,i=r.x,s=r.y,o=e||n.get(S),u=t||n.get(E),a=n._minScrollX,f=n._minScrollY,l=n._maxScrollX,c=n._maxScrollY;return i&&(o<a||o>l)||s&&(u<f||u>c)},_snapBack:function(){var e=this,t=e.get(S),n=e.get(E),r=e._minScrollX,i=e._minScrollY,s=e._maxScrollX,o=e._maxScrollY,u=q(n,i,o),a=q(t,r,s),f=e.get(H),l=e.get(B);a!==t?e.set(S,a,{duration:f,easing:l}):u!==n?e.set(E,u,{duration:f,easing:l}):e._onTransEnd()},_afterScrollChange:function(e){if(e.src===R.UI_SRC)return!1;var t=this,n=e.duration,r=e.easing,i=e.newVal,s=[];t.lastScrolledAmt=t.lastScrolledAmt+(e.newVal-e.prevVal),e.attrName===S?(s.push(i),s.push(t.get(E))):(s.push(t.get(S)),s.push(i)),s.push(n),s.push(r),t.scrollTo.apply(t,s)},_afterFlickChange:function(e){this._bindFlick(e.newVal)},_afterDisabledChange:function(e){this._cDisabled=e.newVal},_afterAxisChange:function(e){this._cAxis=e.newVal},_afterDragChange:function(e){this._bindDrag(e.newVal)},_afterDimChange:function(){this._uiDimensionsChange()},_afterScrollEnd:function(e){var t=this;t._flickAnim&&(t._flickAnim.cancel(),delete t._flickAnim),t._isOutOfBounds()&&t._snapBack()},_axisSetter:function(t,n){if(e.Lang.isString(t))return{x:t.match(/x/i)?!0:!1,y:t.match(/y/i)?!0:!1}},_setScroll:function(t,n){return this._cDisabled&&(t=e.Attribute.INVALID_VALUE),t},_setScrollX:function(e){return this._setScroll(e,C)},_setScrollY:function(e){return this._setScroll(e,k)}},{NAME:"scrollview",ATTRS:{axis:{setter:"_axisSetter",writeOnce:"initOnly"},scrollX:{value:0,setter:"_setScrollX"},scrollY:{value:0,setter:"_setScrollY"},deceleration:{value:.93},bounce:{value:.1},flick:{value:{minDistance:10,minVelocity:.3}},drag:{value:!0},snapDuration:{value:400},snapEasing:{value:"ease-out"},easing:{value:"cubic-bezier(0, 0.1, 0, 1.0)"},frameDuration:{value:15},bounceRange:{value:150}},CLASS_NAMES:f,UI_SRC:d,_TRANSITION:{DURATION:u?u+"TransitionDuration":"transitionDuration",PROPERTY:u?u+"TransitionProperty":"transitionProperty"},BOUNCE_RANGE:!1,FRAME_STEP:!1,EASING:!1,SNAP_EASING:!1,SNAP_DURATION:!1})},"3.7.3",{requires:["widget","event-gestures","event-mousewheel","transition"],skinnable:!0});
diff --git a/js/yui3/scrollview-list/assets/scrollview-list-core.css b/js/yui3/scrollview-list/assets/scrollview-list-core.css
new file mode 100644
index 000000000..ab590e648
--- /dev/null
+++ b/js/yui3/scrollview-list/assets/scrollview-list-core.css
@@ -0,0 +1,6 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
diff --git a/js/yui3/scrollview-list/assets/skins/night/scrollview-list.css b/js/yui3/scrollview-list/assets/skins/night/scrollview-list.css
new file mode 100644
index 000000000..7787732bb
--- /dev/null
+++ b/js/yui3/scrollview-list/assets/skins/night/scrollview-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-night .yui3-scrollview{-webkit-tap-highlight-color:rgba(0,0,0,0)}.yui3-skin-night .yui3-scrollview{color:#fff;background-color:#000}.yui3-skin-night .yui3-scrollview-vert .yui3-scrollview-content{border-top:0;background-color:#000;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:#fff}.yui3-skin-night .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{*zoom:1}.yui3-skin-night .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-list{*zoom:1;list-style:none;padding:0;margin:0}.yui3-skin-night .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{border-bottom:1px solid #303030;padding:15px 20px 16px;font-size:100%;font-weight:bold;background-color:#151515;cursor:pointer}.yui3-skin-night .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-list.selected{background-color:#2c2d2e;background:-moz-linear-gradient(0% 100% 90deg,#252626 0,#333434 100%);background:-webkit-gradient(linear,left top,left bottom,from(#333434),to(#252626));border-top:solid 1px #4b4b4b;border-bottom:solid 1px #3e3f3f;margin-top:-1px}#yui3-css-stamp.skin-night-scrollview-list{display:none}
diff --git a/js/yui3/scrollview-list/assets/skins/sam/scrollview-list.css b/js/yui3/scrollview-list/assets/skins/sam/scrollview-list.css
new file mode 100644
index 000000000..aad28c9af
--- /dev/null
+++ b/js/yui3/scrollview-list/assets/skins/sam/scrollview-list.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-scrollview{-webkit-tap-highlight-color:rgba(255,255,255,0)}.yui3-skin-sam .yui3-scrollview{background-color:white}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{*zoom:1}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-list{*zoom:1;list-style:none;padding:0;margin:0}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content{border-top:0;background-color:white;font-family:HelveticaNeue,arial,helvetica,clean,sans-serif;color:black}.yui3-skin-sam .yui3-scrollview-vert .yui3-scrollview-content .yui3-scrollview-item{border-bottom:1px solid #303030;padding:15px 20px 16px;font-size:100%;font-weight:bold;background-color:white;cursor:pointer}#yui3-css-stamp.skin-sam-scrollview-list{display:none}
diff --git a/js/yui3/scrollview-list/scrollview-list-min.js b/js/yui3/scrollview-list/scrollview-list-min.js
new file mode 100644
index 000000000..f03159239
--- /dev/null
+++ b/js/yui3/scrollview-list/scrollview-list-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview-list",function(e,t){function l(){l.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="scrollview",i=n(r,"list"),s=n(r,"item"),o="contentBox",u="rendered",a="renderUI",f="host";l.NAME="pluginList",l.NS="list",l.ATTRS={isAttached:{value:!1,validator:e.Lang.isBoolean}},e.namespace("Plugin").ScrollViewList=e.extend(l,e.Plugin.Base,{initializer:function(){this._host=this.get(f),this.afterHostEvent("render",this._addClassesToList)},_addClassesToList:function(){if(!this.get("isAttached")){var e=this._host.get(o),t,n;e.hasChildNodes()&&(t=e.all("> ul"),n=e.all("> ul > li"),t.each(function(e){e.addClass(i)}),n.each(function(e){e.addClass(s)}),this.set("isAttached",!0),this._host.syncUI())}}})},"3.7.3",{requires:["plugin","classnamemanager"],skinnable:!0});
diff --git a/js/yui3/scrollview-paginator/scrollview-paginator-min.js b/js/yui3/scrollview-paginator/scrollview-paginator-min.js
new file mode 100644
index 000000000..fe9d434f7
--- /dev/null
+++ b/js/yui3/scrollview-paginator/scrollview-paginator-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview-paginator",function(e,t){function w(){w.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r="scrollview",i=n(r,"hidden"),s=n(r,"paged"),o=e.ScrollView?e.ScrollView.UI_SRC:"ui",u="index",a="scrollX",f="scrollY",l="total",c="host",h="boundingBox",p="contentBox",d="selector",v="flick",m="drag",g="axis",y="x",b="y";e.extend(w,e.Plugin.Base,{initializer:function(e){var t=this,n=t.get(c);t._pageDims=[],t._pageBuffer=1,t._optimizeMemory=!1,t._host=n,t._bb=n._bb,t._cb=n._cb,t._cIndex=t.get(u),t._cAxis=t.get(g),e._optimizeMemory&&(t._optimizeMemory=e._optimizeMemory),e._pageBuffer&&(t._pageBuffer=e._pageBuffer),t._bindAttrs()},_bindAttrs:function(){var e=this;e.after({indexChange:e._afterIndexChange,axisChange:e._afterAxisChange}),e.beforeHostMethod("scrollTo",e._beforeHostScrollTo),e.beforeHostMethod("_mousewheel",e._beforeHostMousewheel),e.beforeHostMethod("_flick",e._beforeHostFlick),e.afterHostMethod("_onGestureMoveEnd",e._afterHostGestureMoveEnd),e.afterHostMethod("_uiDimensionsChange",e._afterHostUIDimensionsChange),e.afterHostMethod("syncUI",e._afterHostSyncUI),e.afterHostEvent("render",e._afterHostRender),e.afterHostEvent("scrollEnd",e._afterHostScrollEnded)},_afterHostRender:function(e){var t=this,n=t._bb,r=t._host,i=t._cIndex,o=t._cAxis,u=t._getPageNodes(),a=u.size(),f=t._pageDims[i].maxScrollX,c=t._pageDims[i].maxScrollY;o[b]?r._maxScrollX=f:o[y]&&(r._maxScrollY=c),t.set(l,a),i!==0&&t.scrollToIndex(i,0),n.addClass(s),t._optimize()},_afterHostSyncUI:function(e){var t=this,n=t._host,r=n.get(v),i=t._getPageNodes(),s=i.size(),o;t.set(l,s),t._cAxis===undefined&&t._set(g,n.get(g))},_afterHostUIDimensionsChange:function(e){var t=this,n=t._host,r=n._getScrollDims(),i=r.offsetWidth,s=r.offsetHeight,o=t._getPageNodes();o.each(function(e,n){var r=e.get("scrollWidth"),o=e.get("scrollHeight"),u=Math.max(0,r-i),a=Math.max(0,o-s);t._pageDims[n]?(t._pageDims[n].maxScrollX=u,t._pageDims[n].maxScrollY=a):t._pageDims[n]={scrollX:0,scrollY:0,_minScrollX:0,_minScrollY:0,maxScrollX:u,maxScrollY:a}})},_beforeHostScrollTo:function(t,n,r,i,s){var o=this,u=o._host,a=u._gesture,f=o._cIndex,l=o._cAxis,c=this._getPageNodes(),h;return a&&(h=a.axis,h===b?t=null:n=null,l[h]===!1&&(s=c.item(f))),new e.Do.AlterArgs("new args",[t,n,r,i,s])},_afterHostGestureMoveEnd:function(e){var t=this,n=t._host,r=n._gesture,i=t._cAxis,s=r&&r.axis;i[s]&&(r[s===y?"deltaX":"deltaY"]>0?t[n.rtl?"prev":"next"]():t[n.rtl?"next":"prev"]())},_beforeHostMousewheel:function(t){var n=this,r=n._host,i=r._bb,s=t.wheelDelta<0,o=n._cAxis;r._gesture={axis:b};if(i.contains(t.target)&&o[b])return s?n.next():n.prev(),t.preventDefault(),new e.Do.Prevent},_beforeHostFlick:function(t){var n=this,r=n.get(g),i=t.flick.axis||!1;if(r[i])return new e.Do.Prevent},_afterHostScrollEnded:function(e){var t=this,n=t._host,r=t._cIndex,i=n.get(a),s=n.get(f),o=t._cAxis;o[b]?t._pageDims[r].scrollX=i:t._pageDims[r].scrollY=s,t._optimize()},_afterIndexChange:function(e){var t=this,n=t._host,r=e.newVal,i=t._pageDims[r],s=n._cAxis,u=t._cAxis;t._cIndex=r,s[y]&&s[b]&&(u[b]?(n._maxScrollX=i.maxScrollX,n.set(a,i.scrollX,{src:o})):u[y]&&(n._maxScrollY=i.maxScrollY,n.set(f,i.scrollY,{src:o}))),e.src!==o&&t.scrollToIndex(r)},_optimize:function(){if(!this._optimizeMemory)return!1;var e=this,t=e._cIndex,n=e._getStage(t);e._showNodes(n.visible),e._hideNodes(n.hidden)},_getStage:function(e){var t=this._pageBuffer,n=this.get(l),r=this._getPageNodes(),i=Math.max(0,e-t),s=Math.min(n,e+1+t);return{visible:r.splice(i,s-i),hidden:r}},_showNodes:function(e){e&&e.removeClass(i).setStyle("visibility","")},_hideNodes:function(e){e&&e.addClass(i).setStyle("visibility","hidden")},_getPageNodes:function(){var e=this,t=e._host,n=t._cb,r=e.get(d),i=r?n.all(r):n.get("children");return i},next:function(){var e=this,t=e._cIndex,n=t+1,r=this.get(l);if(n>=r)return;e.set(u,n)},prev:function(){var e=this,t=e._cIndex,n=t-1;if(n<0)return;e.set(u,n)},scrollTo:function(){return this.scrollToIndex.apply(this,arguments)},scrollToIndex:function(e,t,n){var r=this,i=r._host,s=r._getPageNodes().item(e),o=r._cAxis[y]?a:f,l=s.get(o===a?"offsetLeft":"offsetTop");t=t!==undefined?t:w.TRANSITION.duration,n=n!==undefined?t:w.TRANSITION.easing,r.set(u,e),r._showNodes(s),i.set(o,l,{duration:t,easing:n})},_axisSetter:function(t,n){if(e.Lang.isString(t))return{x:t.match(/x/i)?!0:!1,y:t.match(/y/i)?!0:!1}},_afterAxisChange:function(e){this._cAxis=e.newVal}},{NAME:"pluginScrollViewPaginator",NS:"pages",ATTRS:{axis:{setter:"_axisSetter",writeOnce:"initOnly"},selector:{value:null},index:{value:0,validator:function(e){return!0}},total:{value:0}},TRANSITION:{duration:300,easing:"ease-out"}}),e.namespace("Plugin").ScrollViewPaginator=w},"3.7.3",{requires:["plugin","classnamemanager"]});
diff --git a/js/yui3/scrollview-scrollbars/assets/scrollview-scrollbars-core.css b/js/yui3/scrollview-scrollbars/assets/scrollview-scrollbars-core.css
new file mode 100644
index 000000000..4af9a3ac1
--- /dev/null
+++ b/js/yui3/scrollview-scrollbars/assets/scrollview-scrollbars-core.css
@@ -0,0 +1,101 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview-scrollbar {
+ opacity: 1;
+ position: absolute;
+ width: 6px;
+ height: 10px;
+}
+
+.yui3-scrollview-scrollbar {
+ top: 0;
+ right: 1px;
+}
+
+.yui3-scrollview-scrollbar-horiz {
+ top:auto;
+ height: 8px;
+ width: 20px;
+ bottom: 1px;
+ left: 0;
+}
+
+.yui3-scrollview-scrollbar .yui3-scrollview-child {
+ position: absolute;
+ right: 0px;
+ display: block;
+ width: 100%;
+ height: 4px;
+}
+
+.yui3-scrollview-scrollbar .yui3-scrollview-first {
+ top: 0;
+}
+
+.yui3-scrollview-scrollbar .yui3-scrollview-last {
+ top: 0;
+}
+
+.yui3-scrollview-scrollbar .yui3-scrollview-middle {
+ position: absolute;
+ top: 4px;
+ height: 1px;
+}
+
+.yui3-scrollview-scrollbar-horiz .yui3-scrollview-child {
+ display:-moz-inline-stack;
+ display:inline-block;
+ zoom:1;
+ *display:inline;
+
+ top: 0;
+ left: 0;
+ bottom: auto;
+ right: auto;
+}
+
+.yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,
+.yui3-scrollview-scrollbar-horiz .yui3-scrollview-last {
+ width: 4px;
+ height: 6px;
+}
+
+.yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle {
+ top: 0;
+ left: 4px;
+ width: 1px;
+ height: 6px;
+}
+
+.yui3-scrollview-scrollbar-vert-basic {
+ height:auto;
+}
+
+.yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child {
+ position:static;
+ _overflow:hidden;
+ _line-height:4px;
+}
+
+.yui3-scrollview-scrollbar-horiz-basic {
+ width:auto;
+ white-space:nowrap;
+ line-height:6px;
+ _overflow:hidden;
+}
+
+.yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child {
+ position:static;
+
+ padding:0;
+ margin:0;
+
+ top:auto;
+ left:auto;
+ right:auto;
+ bottom:auto;
+} \ No newline at end of file
diff --git a/js/yui3/scrollview-scrollbars/assets/skins/night/scrollview-scrollbars.css b/js/yui3/scrollview-scrollbars/assets/skins/night/scrollview-scrollbars.css
new file mode 100644
index 000000000..e259b756b
--- /dev/null
+++ b/js/yui3/scrollview-scrollbars/assets/skins/night/scrollview-scrollbars.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview-scrollbar{opacity:1;position:absolute;width:6px;height:10px}.yui3-scrollview-scrollbar{top:0;right:1px}.yui3-scrollview-scrollbar-horiz{top:auto;height:8px;width:20px;bottom:1px;left:0}.yui3-scrollview-scrollbar .yui3-scrollview-child{position:absolute;right:0;display:block;width:100%;height:4px}.yui3-scrollview-scrollbar .yui3-scrollview-first{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-last{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-middle{position:absolute;top:4px;height:1px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-child{display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline;top:0;left:0;bottom:auto;right:auto}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{width:4px;height:6px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{top:0;left:4px;width:1px;height:6px}.yui3-scrollview-scrollbar-vert-basic{height:auto}.yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child{position:static;_overflow:hidden;_line-height:4px}.yui3-scrollview-scrollbar-horiz-basic{width:auto;white-space:nowrap;line-height:6px;_overflow:hidden}.yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{position:static;padding:0;margin:0;top:auto;left:auto;right:auto;bottom:auto}.yui3-skin-night .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-color:#808080;opacity:.3;filter:alpha(opacity=30)}.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-night .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-night .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-night .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-night .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-night .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-night .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-night .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none}#yui3-css-stamp.skin-night-scrollview-scrollbars{display:none}
diff --git a/js/yui3/scrollview-scrollbars/assets/skins/sam/scrollview-scrollbars.css b/js/yui3/scrollview-scrollbars/assets/skins/sam/scrollview-scrollbars.css
new file mode 100644
index 000000000..8a8332586
--- /dev/null
+++ b/js/yui3/scrollview-scrollbars/assets/skins/sam/scrollview-scrollbars.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-scrollview-scrollbar{opacity:1;position:absolute;width:6px;height:10px}.yui3-scrollview-scrollbar{top:0;right:1px}.yui3-scrollview-scrollbar-horiz{top:auto;height:8px;width:20px;bottom:1px;left:0}.yui3-scrollview-scrollbar .yui3-scrollview-child{position:absolute;right:0;display:block;width:100%;height:4px}.yui3-scrollview-scrollbar .yui3-scrollview-first{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-last{top:0}.yui3-scrollview-scrollbar .yui3-scrollview-middle{position:absolute;top:4px;height:1px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-child{display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline;top:0;left:0;bottom:auto;right:auto}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{width:4px;height:6px}.yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{top:0;left:4px;width:1px;height:6px}.yui3-scrollview-scrollbar-vert-basic{height:auto}.yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child{position:static;_overflow:hidden;_line-height:4px}.yui3-scrollview-scrollbar-horiz-basic{width:auto;white-space:nowrap;line-height:6px;_overflow:hidden}.yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{position:static;padding:0;margin:0;top:auto;left:auto;right:auto;bottom:auto}.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none}#yui3-css-stamp.skin-sam-scrollview-scrollbars{display:none}
diff --git a/js/yui3/scrollview-scrollbars/scrollview-scrollbars-min.js b/js/yui3/scrollview-scrollbars/scrollview-scrollbars-min.js
new file mode 100644
index 000000000..1bedc7608
--- /dev/null
+++ b/js/yui3/scrollview-scrollbars/scrollview-scrollbars-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview-scrollbars",function(e,t){function O(){O.superclass.constructor.apply(this,arguments)}var n=e.ClassNameManager.getClassName,r,i=e.Transition,s=i.useNative,o="scrollbar",u="scrollview",a="verticalNode",f="horizontalNode",l="childCache",c="top",h="left",p="width",d="height",v="scrollWidth",m="scrollHeight",g="_sbh",y="_sbv",b=e.ScrollView._TRANSITION.PROPERTY,w="transform",E="translateX(",S="translateY(",x="scaleX(",T="scaleY(",N="scrollX",C="scrollY",k="px",L=")",A=k+L;O.CLASS_NAMES={showing:n(u,o,"showing"),scrollbar:n(u,o),scrollbarV:n(u,o,"vert"),scrollbarH:n(u,o,"horiz"),scrollbarVB:n(u,o,"vert","basic"),scrollbarHB:n(u,o,"horiz","basic"),child:n(u,"child"),first:n(u,"first"),middle:n(u,"middle"),last:n(u,"last")},r=O.CLASS_NAMES,O.NAME="pluginScrollViewScrollbars",O.NS="scrollbars",O.SCROLLBAR_TEMPLATE=["<div>",'<span class="'+r.child+" "+r.first+'"></span>','<span class="'+r.child+" "+r.middle+'"></span>','<span class="'+r.child+" "+r.last+'"></span>',"</div>"].join(""),O.ATTRS={verticalNode:{setter:"_setNode",valueFn:"_defaultNode"},horizontalNode:{setter:"_setNode",valueFn:"_defaultNode"}},e.namespace("Plugin").ScrollViewScrollbars=e.extend(O,e.Plugin.Base,{initializer:function(){this._host=this.get("host"),this.afterHostEvent("scrollEnd",this._hostScrollEnd),this.afterHostMethod("scrollTo",this._update),this.afterHostMethod("_uiDimensionsChange",this._hostDimensionsChange)},_hostDimensionsChange:function(){var t=this._host,n=t._cAxis;this._dims=t._getScrollDims(),n&&n.y&&this._renderBar(this.get(a),!0,"vert"),n&&n.x&&this._renderBar(this.get(f),!0,"horiz"),this._update(),e.later(500,this,"flash",!0)},_hostScrollEnd:function(e){this._host._flicking||this.flash()},_renderBar:function(e,t){var n=e.inDoc(),i=this._host._bb,s=e.getData("isHoriz")?r.scrollbarHB:r.scrollbarVB;t&&!n?(i.append(e),e.toggleClass(s,this._basic),this._setChildCache(e)):!t&&n&&(e.remove(),this._clearChildCache(e))},_setChildCache:function(e){var t=e.get("children"),n=t.item(0),r=t.item(1),i=t.item(2),s=e.getData("isHoriz")?"offsetWidth":"offsetHeight";e.setStyle(b,w),r.setStyle(b,w),i.setStyle(b,w),e.setData(l,{fc:n,lc:i,mc:r,fcSize:n&&n.get(s),lcSize:i&&i.get(s)})},_clearChildCache:function(e){e.clearData(l)},_updateBar:function(e,t,n,r){var i=this._host,o=this._basic,u=i._cb,a=0,f=1,v=e.getData(l),m=v.lc,b=v.mc,O=v.fcSize,M=v.lcSize,_,D,P,H,B,j,F,I,q,R;r?(j=p,F=h,I=g,q=this._dims.offsetWidth,R=this._dims.scrollWidth,H=E,B=x,t=t!==undefined?t:i.get(N)):(j=d,F=c,I=y,q=this._dims.offsetHeight,R=this._dims.scrollHeight,H=S,B=T,t=t!==undefined?t:i.get(C)),a=Math.floor(q*(q/R)),f=Math.floor(t/(R-q)*(q-a)),a>q&&(a=1),f>q-a?a-=f-(q-a):f<0&&(a=f+a,f=0),_=a-(O+M),_<0&&(_=0),_===0&&f!==0&&(f=q-(O+M)-1),n!==0?(P={duration:n},s?P.transform=H+f+A:P[F]=f+k,e.transition(P)):s?e.setStyle(w,H+f+A):e.setStyle(F,f+k);if(this[I]!==_){this[I]=_;if(_>0){n!==0?(P={duration:n},s?P.transform=B+_+L:P[j]=_+k,b.transition(P)):s?b.setStyle(w,B+_+L):b.setStyle(j,_+k);if(!r||!o)D=a-M,n!==0?(P={duration:n},s?P.transform=H+D+A:P[F]=D,m.transition(P)):s?m.setStyle(w,H+D+A):m.setStyle(F,D+k)}}},_update:function(e,t,n,r){var i=this.get(a),s=this.get(f),o=this._host,u=o._cAxis;n=(n||0)/1e3,this._showing||this.show(),u&&u.y&&i&&this._updateBar(i,t,n,!1),u&&u.x&&s&&this._updateBar(s,e,n,!0)},show:function(e){this._show(!0,e)},hide:function(e){this._show(!1,e)},_show:function(e,t){var n=this.get(a),r=this.get(f),i=t?.6:0,s=e?1:0,o;this._showing=e,this._flashTimer&&this._flashTimer.cancel(),o={duration:i,opacity:s},n&&n.transition(o),r&&r.transition(o)},flash:function(){var t=this._host;this.show(!0),this._flashTimer=e.later(800,this,"hide",!0)},_setNode:function(t,n){var i=n===f;return t=e.one(t),t&&(t.addClass(r.scrollbar),t.addClass(i?r.scrollbarH:r.scrollbarV),t.setData("isHoriz",i)),t},_defaultNode:function(){return e.Node.create(O.SCROLLBAR_TEMPLATE)},_basic:e.UA.ie&&e.UA.ie<=8})},"3.7.3",{requires:["classnamemanager","transition","plugin"],skinnable:!0});
diff --git a/js/yui3/scrollview/scrollview-min.js b/js/yui3/scrollview/scrollview-min.js
new file mode 100644
index 000000000..f64fa20a0
--- /dev/null
+++ b/js/yui3/scrollview/scrollview-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("scrollview",function(e,t){e.Base.plug(e.ScrollView,e.Plugin.ScrollViewScrollbars)},"3.7.3",{requires:["scrollview-base","scrollview-scrollbars"]});
diff --git a/js/yui3/selector-css2/selector-css2-min.js b/js/yui3/selector-css2/selector-css2-min.js
new file mode 100644
index 000000000..a6eec8efd
--- /dev/null
+++ b/js/yui3/selector-css2/selector-css2-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("selector-css2",function(e,t){var n="parentNode",r="tagName",i="attributes",s="combinator",o="pseudos",u=e.Selector,a={_reRegExpTokens:/([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,SORT_RESULTS:!0,_isXML:function(){var t=e.config.doc.createElement("div").tagName!=="DIV";return t}(),shorthand:{"\\#(-?[_a-z0-9]+[-\\w\\uE000]*)":"[id=$1]","\\.(-?[_a-z]+[-\\w\\uE000]*)":"[className~=$1]"},operators:{"":function(t,n){return e.DOM.getAttribute(t,n)!==""},"~=":"(?:^|\\s+){val}(?:\\s+|$)","|=":"^{val}-?"},pseudos:{"first-child":function(t){return e.DOM._children(t[n])[0]===t}},_bruteQuery:function(t,n,r){var i=[],s=[],o=u._tokenize(t),a=o[o.length-1],f=e.DOM._getDoc(n),l,c,h,p;if(a){c=a.id,h=a.className,p=a.tagName||"*";if(n.getElementsByTagName)c&&(n.all||n.nodeType===9||e.DOM.inDoc(n))?s=e.DOM.allById(c,n):h?s=n.getElementsByClassName(h):s=n.getElementsByTagName(p);else{l=n.firstChild;while(l)l.tagName&&(p==="*"||l.tagName===p)&&s.push(l),l=l.nextSibling||l.firstChild}s.length&&(i=u._filterNodes(s,o,r))}return i},_filterNodes:function(t,n,r){var i=0,s,o=n.length,a=o-1,f=[],l=t[0],c=l,h=e.Selector.getters,p,d,v,m,g,y,b,w;for(i=0;c=l=t[i++];){a=o-1,m=null;e:while(c&&c.tagName){v=n[a],b=v.tests,s=b.length;if(s&&!g)while(w=b[--s]){p=w[1],h[w[0]]?y=h[w[0]](c,w[0]):(y=c[w[0]],w[0]==="tagName"&&!u._isXML&&(y=y.toUpperCase()),typeof y!="string"&&y!==undefined&&y.toString?y=y.toString():y===undefined&&c.getAttribute&&(y=c.getAttribute(w[0],2)));if(p==="="&&y!==w[2]||typeof p!="string"&&p.test&&!p.test(y)||!p.test&&typeof p=="function"&&!p(c,w[0],w[2])){if(c=c[m])while(c&&(!c.tagName||v.tagName&&v.tagName!==c.tagName))c=c[m];continue e}}a--;if(!!g||!(d=v.combinator)){f.push(l);if(r)return f;break}m=d.axis,c=c[m];while(c&&!c.tagName)c=c[m];d.direct&&(m=null)}}return l=c=null,f},combinators:{" ":{axis:"parentNode"},">":{axis:"parentNode",direct:!0},"+":{axis:"previousSibling",direct:!0}},_parsers:[{name:i,re:/^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,fn:function(t,n){var r=t[2]||"",i=u.operators,s=t[3]?t[3].replace(/\\/g,""):"",o;if(t[1]==="id"&&r==="="||t[1]==="className"&&e.config.doc.documentElement.getElementsByClassName&&(r==="~="||r==="="))n.prefilter=t[1],t[3]=s,n[t[1]]=t[1]==="id"?t[3]:s;r in i&&(o=i[r],typeof o=="string"&&(t[3]=s.replace(u._reRegExpTokens,"\\$1"),o=new RegExp(o.replace("{val}",t[3]))),t[2]=o);if(!n.last||n.prefilter!==t[1])return t.slice(1)}},{name:r,re:/^((?:-?[_a-z]+[\w-]*)|\*)/i,fn:function(e,t){var n=e[1];u._isXML||(n=n.toUpperCase()),t.tagName=n;if(n!=="*"&&(!t.last||t.prefilter))return[r,"=",n];t.prefilter||(t.prefilter="tagName")}},{name:s,re:/^\s*([>+~]|\s)\s*/,fn:function(e,t){}},{name:o,re:/^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,fn:function(e,t){var n=u[o][e[1]];return n?(e[2]&&(e[2]=e[2].replace(/\\/g,"")),[e[2],n]):!1}}],_getToken:function(e){return{tagName:null,id:null,className:null,attributes:{},combinator:null,tests:[]}},_tokenize:function(t){t=t||"",t=u._parseSelector(e.Lang.trim(t));var n=u._getToken(),r=t,i=[],o=!1,a,f,l,c;e:do{o=!1;for(l=0;c=u._parsers[l++];)if(a=c.re.exec(t)){c.name!==s&&(n.selector=t),t=t.replace(a[0],""),t.length||(n.last=!0),u._attrFilters[a[1]]&&(a[1]=u._attrFilters[a[1]]),f=c.fn(a,n);if(f===!1){o=!1;break e}f&&n.tests.push(f);if(!t.length||c.name===s)i.push(n),n=u._getToken(n),c.name===s&&(n.combinator=e.Selector.combinators[a[1]]);o=!0}}while(o&&t.length);if(!o||t.length)i=[];return i},_replaceMarkers:function(e){return e=e.replace(/\[/g,"\ue003"),e=e.replace(/\]/g,"\ue004"),e=e.replace(/\(/g,"\ue005"),e=e.replace(/\)/g,"\ue006"),e},_replaceShorthand:function(t){var n=e.Selector.shorthand,r;for(r in n)n.hasOwnProperty(r)&&(t=t.replace(new RegExp(r,"gi"),n[r]));return t},_parseSelector:function(t){var n=e.Selector._replaceSelector(t),t=n.selector;return t=e.Selector._replaceShorthand(t),t=e.Selector._restore("attr",t,n.attrs),t=e.Selector._restore("pseudo",t,n.pseudos),t=e.Selector._replaceMarkers(t),t=e.Selector._restore("esc",t,n.esc),t},_attrFilters:{"class":"className","for":"htmlFor"},getters:{href:function(t,n){return e.DOM.getAttribute(t,n)},id:function(t,n){return e.DOM.getId(t)}}};e.mix(e.Selector,a,!0),e.Selector.getters.src=e.Selector.getters.rel=e.Selector.getters.href,e.Selector.useNative&&e.config.doc.querySelector&&(e.Selector.shorthand["\\.(-?[_a-z]+[-\\w]*)"]="[class~=$1]")},"3.7.3",{requires:["selector-native"]});
diff --git a/js/yui3/selector-css3/selector-css3-min.js b/js/yui3/selector-css3/selector-css3-min.js
new file mode 100644
index 000000000..7f40e97c8
--- /dev/null
+++ b/js/yui3/selector-css3/selector-css3-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("selector-css3",function(e,t){e.Selector._reNth=/^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/,e.Selector._getNth=function(t,n,r,i){e.Selector._reNth.test(n);var s=parseInt(RegExp.$1,10),o=RegExp.$2,u=RegExp.$3,a=parseInt(RegExp.$4,10)||0,f=[],l=e.DOM._children(t.parentNode,r),c;u?(s=2,c="+",o="n",a=u==="odd"?1:0):isNaN(s)&&(s=o?1:0);if(s===0)return i&&(a=l.length-a+1),l[a-1]===t?!0:!1;s<0&&(i=!!i,s=Math.abs(s));if(!i){for(var h=a-1,p=l.length;h<p;h+=s)if(h>=0&&l[h]===t)return!0}else for(var h=l.length-a,p=l.length;h>=0;h-=s)if(h<p&&l[h]===t)return!0;return!1},e.mix(e.Selector.pseudos,{root:function(e){return e===e.ownerDocument.documentElement},"nth-child":function(t,n){return e.Selector._getNth(t,n)},"nth-last-child":function(t,n){return e.Selector._getNth(t,n,null,!0)},"nth-of-type":function(t,n){return e.Selector._getNth(t,n,t.tagName)},"nth-last-of-type":function(t,n){return e.Selector._getNth(t,n,t.tagName,!0)},"last-child":function(t){var n=e.DOM._children(t.parentNode);return n[n.length-1]===t},"first-of-type":function(t){return e.DOM._children(t.parentNode,t.tagName)[0]===t},"last-of-type":function(t){var n=e.DOM._children(t.parentNode,t.tagName);return n[n.length-1]===t},"only-child":function(t){var n=e.DOM._children(t.parentNode);return n.length===1&&n[0]===t},"only-of-type":function(t){var n=e.DOM._children(t.parentNode,t.tagName);return n.length===1&&n[0]===t},empty:function(e){return e.childNodes.length===0},not:function(t,n){return!e.Selector.test(t,n)},contains:function(e,t){var n=e.innerText||e.textContent||"";return n.indexOf(t)>-1},checked:function(e){return e.checked===!0||e.selected===!0},enabled:function(e){return e.disabled!==undefined&&!e.disabled},disabled:function(e){return e.disabled}}),e.mix(e.Selector.operators,{"^=":"^{val}","$=":"{val}$","*=":"{val}"}),e.Selector.combinators["~"]={axis:"previousSibling"}},"3.7.3",{requires:["selector-native","selector-css2"]});
diff --git a/js/yui3/selector-native/selector-native-min.js b/js/yui3/selector-native/selector-native-min.js
new file mode 100644
index 000000000..64a0711bf
--- /dev/null
+++ b/js/yui3/selector-native/selector-native-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("selector-native",function(e,t){(function(e){e.namespace("Selector");var t="compareDocumentPosition",n="ownerDocument",r={_types:{esc:{token:"\ue000",re:/\\[:\[\]\(\)#\.\'\>+~"]/gi},attr:{token:"\ue001",re:/(\[[^\]]*\])/g},pseudo:{token:"\ue002",re:/(\([^\)]*\))/g}},useNative:!0,_escapeId:function(e){return e&&(e=e.replace(/([:\[\]\(\)#\.'<>+~"])/g,"\\$1")),e},_compare:"sourceIndex"in e.config.doc.documentElement?function(e,t){var n=e.sourceIndex,r=t.sourceIndex;return n===r?0:n>r?1:-1}:e.config.doc.documentElement[t]?function(e,n){return e[t](n)&4?-1:1}:function(e,t){var r,i,s;return e&&t&&(r=e[n].createRange(),r.setStart(e,0),i=t[n].createRange(),i.setStart(t,0),s=r.compareBoundaryPoints(1,i)),s},_sort:function(t){return t&&(t=e.Array(t,0,!0),t.sort&&t.sort(r._compare)),t},_deDupe:function(e){var t=[],n,r;for(n=0;r=e[n++];)r._found||(t[t.length]=r,r._found=!0);for(n=0;r=t[n++];)r._found=null,r.removeAttribute("_found");return t},query:function(t,n,i,s){n=n||e.config.doc;var o=[],u=e.Selector.useNative&&e.config.doc.querySelector&&!s,a=[[t,n]],f,l,c,h=u?e.Selector._nativeQuery:e.Selector._bruteQuery;if(t&&h){!s&&(!u||n.tagName)&&(a=r._splitQueries(t,n));for(c=0;f=a[c++];)l=h(f[0],f[1],i),i||(l=e.Array(l,0,!0)),l&&(o=o.concat(l));a.length>1&&(o=r._sort(r._deDupe(o)))}return i?o[0]||null:o},_replaceSelector:function(t){var n=e.Selector._parse("esc",t),i,s;return t=e.Selector._replace("esc",t),s=e.Selector._parse("pseudo",t),t=r._replace("pseudo",t),i=e.Selector._parse("attr",t),t=e.Selector._replace("attr",t),{esc:n,attrs:i,pseudos:s,selector:t}},_restoreSelector:function(t){var n=t.selector;return n=e.Selector._restore("attr",n,t.attrs),n=e.Selector._restore("pseudo",n,t.pseudos),n=e.Selector._restore("esc",n,t.esc),n},_replaceCommas:function(t){var n=e.Selector._replaceSelector(t),t=n.selector;return t&&(t=t.replace(/,/g,"\ue007"),n.selector=t,t=e.Selector._restoreSelector(n)),t},_splitQueries:function(t,n){t.indexOf(",")>-1&&(t=e.Selector._replaceCommas(t));var r=t.split("\ue007"),i=[],s="",o,u,a;if(n){n.nodeType===1&&(o=e.Selector._escapeId(e.DOM.getId(n)),o||(o=e.guid(),e.DOM.setId(n,o)),s='[id="'+o+'"] ');for(u=0,a=r.length;u<a;++u)t=s+r[u],i.push([t,n])}return i},_nativeQuery:function(t,n,r){if(e.UA.webkit&&t.indexOf(":checked")>-1&&e.Selector.pseudos&&e.Selector.pseudos.checked)return e.Selector.query(t,n,r,!0);try{return n["querySelector"+(r?"":"All")](t)}catch(i){return e.Selector.query(t,n,r,!0)}},filter:function(t,n){var r=[],i,s;if(t&&n)for(i=0;s=t[i++];)e.Selector.test(s,n)&&(r[r.length]=s);return r},test:function(t,r,i){var s=!1,o=!1,u,a,f,l,c,h,p,d,v;if(t&&t.tagName)if(typeof r=="function")s=r.call(t,t);else{u=r.split(","),!i&&!e.DOM.inDoc(t)&&(a=t.parentNode,a?i=a:(c=t[n].createDocumentFragment(),c.appendChild(t),i=c,o=!0)),i=i||t[n],h=e.Selector._escapeId(e.DOM.getId(t)),h||(h=e.guid(),e.DOM.setId(t,h));for(p=0;v=u[p++];){v+='[id="'+h+'"]',l=e.Selector.query(v,i);for(d=0;f=l[d++];)if(f===t){s=!0;break}if(s)break}o&&c.removeChild(t)}return s},ancestor:function(t,n,r){return e.DOM.ancestor(t,function(t){return e.Selector.test(t,n)},r)},_parse:function(t,n){return n.match(e.Selector._types[t].re)},_replace:function(t,n){var r=e.Selector._types[t];return n.replace(r.re,r.token)},_restore:function(t,n,r){if(r){var i=e.Selector._types[t].token,s,o;for(s=0,o=r.length;s<o;++s)n=n.replace(i,r[s])}return n}};e.mix(e.Selector,r,!0)})(e)},"3.7.3",{requires:["dom-base"]});
diff --git a/js/yui3/selector/selector-min.js b/js/yui3/selector/selector-min.js
new file mode 100644
index 000000000..6306b1500
--- /dev/null
+++ b/js/yui3/selector/selector-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("selector",function(e,t){},"3.7.3",{requires:["selector-native"]});
diff --git a/js/yui3/shim-plugin/shim-plugin-min.js b/js/yui3/shim-plugin/shim-plugin-min.js
new file mode 100644
index 000000000..658699867
--- /dev/null
+++ b/js/yui3/shim-plugin/shim-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("shim-plugin",function(e,t){function n(e){this.init(e)}n.CLASS_NAME="yui-node-shim",n.TEMPLATE='<iframe class="'+n.CLASS_NAME+'" frameborder="0" title="Node Stacking Shim"'+'src="javascript:false" tabindex="-1" role="presentation"'+'style="position:absolute; z-index:-1;"></iframe>',n.prototype={init:function(e){this._host=e.host,this.initEvents(),this.insert(),this.sync()},initEvents:function(){this._resizeHandle=this._host.on("resize",this.sync,this)},getShim:function(){return this._shim||(this._shim=e.Node.create(n.TEMPLATE,this._host.get("ownerDocument")))},insert:function(){var e=this._host;this._shim=e.insertBefore(this.getShim(),e.get("firstChild"))},sync:function(){var e=this._shim,t=this._host;e&&e.setAttrs({width:t.getStyle("width"),height:t.getStyle("height")})},destroy:function(){var e=this._shim;e&&e.remove(!0),this._resizeHandle.detach()}},n.NAME="Shim",n.NS="shim",e.namespace("Plugin"),e.Plugin.Shim=n},"3.7.3",{requires:["node-style","node-pluginhost"]});
diff --git a/js/yui3/simpleyui/simpleyui-min.js b/js/yui3/simpleyui/simpleyui-min.js
new file mode 100644
index 000000000..9cf12a1c4
--- /dev/null
+++ b/js/yui3/simpleyui/simpleyui-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+typeof YUI!="undefined"&&(YUI._YUI=YUI);var YUI=function(){var e=0,t=this,n=arguments,r=n.length,i=function(e,t){return e&&e.hasOwnProperty&&e instanceof t},s=typeof YUI_config!="undefined"&&YUI_config;i(t,YUI)?(t._init(),YUI.GlobalConfig&&t.applyConfig(YUI.GlobalConfig),s&&t.applyConfig(s),r||t._setup()):t=new YUI;if(r){for(;e<r;e++)t.applyConfig(n[e]);t._setup()}return t.instanceOf=i,t};(function(){var e,t,n="3.7.3",r=".",i="http://yui.yahooapis.com/",s="yui3-js-enabled",o="yui3-css-stamp",u=function(){},a=Array.prototype.slice,f={"io.xdrReady":1,"io.xdrResponse":1,"SWF.eventHandler":1},l=typeof window!="undefined",c=l?window:null,h=l?c.document:null,p=h&&h.documentElement,d=p&&p.className,v={},m=(new Date).getTime(),g=function(e,t,n,r){e&&e.addEventListener?e.addEventListener(t,n,r):e&&e.attachEvent&&e.attachEvent("on"+t,n)},y=function(e,t,n,r){if(e&&e.removeEventListener)try{e.removeEventListener(t,n,r)}catch(i){}else e&&e.detachEvent&&e.detachEvent("on"+t,n)},b=function(){YUI.Env.windowLoaded=!0,YUI.Env.DOMReady=!0,l&&y(window,"load",b)},w=function(e,t){var n=e.Env._loader,r=["loader-base"],i=YUI.Env,s=i.mods;return n?(n.ignoreRegistered=!1,n.onEnd=null,n.data=null,n.required=[],n.loadType=null):(n=new e.Loader(e.config),e.Env._loader=n),s&&s.loader&&(r=[].concat(r,YUI.Env.loaderExtras)),YUI.Env.core=e.Array.dedupe([].concat(YUI.Env.core,r)),n},E=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},S={success:!0};p&&d.indexOf(s)==-1&&(d&&(d+=" "),d+=s,p.className=d),n.indexOf("@")>-1&&(n="3.5.0"),e={applyConfig:function(e){e=e||u;var t,n,r=this.config,i=r.modules,s=r.groups,o=r.aliases,a=this.Env._loader;for(n in e)e.hasOwnProperty(n)&&(t=e[n],i&&n=="modules"?E(i,t):o&&n=="aliases"?E(o,t):s&&n=="groups"?E(s,t):n=="win"?(r[n]=t&&t.contentWindow||t,r.doc=r[n]?r[n].document:null):n!="_yuid"&&(r[n]=t));a&&a._config(e)},_config:function(e){this.applyConfig(e)},_init:function(){var e,t,r=this,s=YUI.Env,u=r.Env,a;r.version=n;if(!u){r.Env={core:["get","features","intl-base","yui-log","yui-later"],loaderExtras:["loader-rollup","loader-yui3"],mods:{},versions:{},base:i,cdn:i+n+"/build/",_idx:0,_used:{},_attached:{},_missed:[],_yidx:0,_uidx:0,_guidp:"y",_loaded:{},_BASE_RE:/(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,parseBasePath:function(e,t){var n=e.match(t),r,i;return n&&(r=RegExp.leftContext||e.slice(0,e.indexOf(n[0])),i=n[3],n[1]&&(r+="?"+n[1]),r={filter:i,path:r}),r},getBase:s&&s.getBase||function(t){var n=h&&h.getElementsByTagName("script")||[],i=u.cdn,s,o,a,f;for(o=0,a=n.length;o<a;++o){f=n[o].src;if(f){s=r.Env.parseBasePath(f,t);if(s){e=s.filter,i=s.path;break}}}return i}},u=r.Env,u._loaded[n]={};if(s&&r!==YUI)u._yidx=++s._yidx,u._guidp=("yui_"+n+"_"+u._yidx+"_"+m).replace(/\./g,"_").replace(/-/g,"_");else if(YUI._YUI){s=YUI._YUI.Env,u._yidx+=s._yidx,u._uidx+=s._uidx;for(a in s)a in u||(u[a]=s[a]);delete YUI._YUI}r.id=r.stamp(r),v[r.id]=r}r.constructor=YUI,r.config=r.config||{bootstrap:!0,cacheUse:!0,debug:!0,doc:h,fetchCSS:!0,throwFail:!0,useBrowserConsole:!0,useNativeES5:!0,win:c},h&&!h.getElementById(o)&&(t=h.createElement("div"),t.innerHTML='<div id="'+o+'" style="position: absolute !important; visibility: hidden !important"></div>',YUI.Env.cssStampEl=t.firstChild,h.body?h.body.appendChild(YUI.Env.cssStampEl):p.insertBefore(YUI.Env.cssStampEl,p.firstChild)),r.config.lang=r.config.lang||"en-US",r.config.base=YUI.config.base||r.Env.getBase(r.Env._BASE_RE);if(!e||!"mindebug".indexOf(e))e="min";e=e?"-"+e:e,r.config.loaderPath=YUI.config.loaderPath||"loader/loader"+e+".js"},_setup:function(e){var t,n=this,r=[],i=YUI.Env.mods,s=n.config.core||[].concat(YUI.Env.core);for(t=0;t<s.length;t++)i[s[t]]&&r.push(s[t]);n._attach(["yui-base"]),n._attach(r),n.Loader&&w(n)},applyTo:function(e,t,n){if(t in f){var r=v[e],i,s,o;if(r){i=t.split("."),s=r;for(o=0;o<i.length;o+=1)s=s[i[o]],s||this.log("applyTo not found: "+t,"warn","yui");return s&&s.apply(r,n)}return null}return this.log(t+": applyTo not allowed","warn","yui"),null},add:function(e,t,n,r){r=r||{};var i=YUI.Env,s={name:e,fn:t,version:n,details:r},o={},u,a,f,l=i.versions;i.mods[e]=s,l[n]=l[n]||{},l[n][e]=s;for(f in v)v.hasOwnProperty(f)&&(a=v[f],o[a.id]||(o[a.id]=!0,u=a.Env._loader,u&&(!u.moduleInfo[e]||u.moduleInfo[e].temp)&&u.addModule(r,e)));return this},_attach:function(e,t){var n,r,i,s,o,u,a,f=YUI.Env.mods,l=YUI.Env.aliases,c=this,h,p=YUI.Env._renderedMods,d=c.Env._loader,v=c.Env._attached,m=e.length,d,g,y,b=[];for(n=0;n<m;n++){r=e[n],i=f[r],b.push(r);if(d&&d.conditions[r])for(h in d.conditions[r])d.conditions[r].hasOwnProperty(h)&&(g=d.conditions[r][h],y=g&&(g.ua&&c.UA[g.ua]||g.test&&g.test(c)),y&&b.push(g.name))}e=b,m=e.length;for(n=0;n<m;n++)if(!v[e[n]]){r=e[n],i=f[r];if(l&&l[r]&&!i){c._attach(l[r]);continue}if(!i)d&&d.moduleInfo[r]&&(i=d.moduleInfo[r],t=!0),!t&&r&&r.indexOf("skin-")===-1&&r.indexOf("css")===-1&&(c.Env._missed.push(r),c.Env._missed=c.Array.dedupe(c.Env._missed),c.message("NOT loaded: "+r,"warn","yui"));else{v[r]=!0;for(h=0;h<c.Env._missed.length;h++)c.Env._missed[h]===r&&(c.message("Found: "+r+" (was reported as missing earlier)","warn","yui"),c.Env._missed.splice(h,1));if(d&&p&&p[r]&&p[r].temp){d.getRequires(p[r]),o=[];for(h in d.moduleInfo[r].expanded_map)d.moduleInfo[r].expanded_map.hasOwnProperty(h)&&o.push(h);c._attach(o)}s=i.details,o=s.requires,u=s.use,a=s.after,s.lang&&(o=o||[],o.unshift("intl"));if(o)for(h=0;h<o.length;h++)if(!v[o[h]]){if(!c._attach(o))return!1;break}if(a)for(h=0;h<a.length;h++)if(!v[a[h]]){if(!c._attach(a,!0))return!1;break}if(i.fn)if(c.config.throwFail)i.fn(c,r);else try{i.fn(c,r)}catch(w){return c.error("Attach error: "+r,w,r),!1}if(u)for(h=0;h<u.length;h++)if(!v[u[h]]){if(!c._attach(u))return!1;break}}}return!0},_delayCallback:function(e,t){var n=this,r=["event-base"];return t=n.Lang.isObject(t)?t:{event:t},t.event==="load"&&r.push("event-synthetic"),function(){var i=arguments;n._use(r,function(){n.on(t.event,function(){i[1].delayUntil=t.event,e.apply(n,i)},t.args)})}},use:function(){var e=a.call(arguments,0),t=e[e.length-1],n=this,r=0,i=[],s,o=n.Env,u=!0;n.Lang.isFunction(t)?(e.pop(),n.config.delayUntil&&(t=n._delayCallback(t,n.config.delayUntil))):t=null,n.Lang.isArray(e[0])&&(e=e[0]);if(n.config.cacheUse){while(s=e[r++])if(!o._attached[s]){u=!1;break}if(u)return e.length,n._notify(t,S,e),n}return n._loading?(n._useQueue=n._useQueue||new n.Queue,n._useQueue.add([e,t])):n._use(e,function(n,r){n._notify(t,r,e)}),n},_notify:function(e,t,n){if(!t.success&&this.config.loadErrorFn)this.config.loadErrorFn.call(this,this,e,t,n);else if(e){this.Env._missed&&this.Env._missed.length&&(t.msg="Missing modules: "+this.Env._missed.join(),t.success=!1);if(this.config.throwFail)e(this,t);else try{e(this,t)}catch(r){this.error("use callback error",r,n)}}},_use:function(e,t){this.Array||this._attach(["yui-base"]);var r,i,s,o,u=this,a=YUI.Env,f=a.mods,l=u.Env,c=l._used,h=a.aliases,p=a._loaderQueue,d=e[0],v=u.Array,m=u.config,g=m.bootstrap,y=[],b,E=[],S=!0,x=m.fetchCSS,T=function(e,t){var r=0,i=[],s,o,u,l,p;if(!e.length)return;if(h){o=e.length;for(r=0;r<o;r++)h[e[r]]&&!f[e[r]]?i=[].concat(i,h[e[r]]):i.push(e[r]);e=i}o=e.length;for(r=0;r<o;r++){s=e[r],t||E.push(s);if(c[s])continue;u=f[s],l=null,p=null,u?(c[s]=!0,l=u.details.requires,p=u.details.use):a._loaded[n][s]?c[s]=!0:y.push(s),l&&l.length&&T(l),p&&p.length&&T(p,1)}},N=function(n){var r=n||{success:!0,msg:"not dynamic"},i,s,o=!0,a=r.data;u._loading=!1,a&&(s=y,y=[],E=[],T(a),i=y.length,i&&[].concat(y).sort().join()==s.sort().join()&&(i=!1)),i&&a?(u._loading=!0,u._use(y,function(){u._attach(a)&&u._notify(t,r,a)})):(a&&(o=u._attach(a)),o&&u._notify(t,r,e)),u._useQueue&&u._useQueue.size()&&!u._loading&&u._use.apply(u,u._useQueue.next())};if(d==="*"){e=[];for(b in f)f.hasOwnProperty(b)&&e.push(b);return S=u._attach(e),S&&N(),u}return(f.loader||f["loader-base"])&&!u.Loader&&u._attach(["loader"+(f.loader?"":"-base")]),g&&u.Loader&&e.length&&(i=w(u),i.require(e),i.ignoreRegistered=!0,i._boot=!0,i.calculate(null,x?null:"js"),e=i.sorted,i._boot=!1),T(e),r=y.length,r&&(y=v.dedupe(y),r=y.length),g&&r&&u.Loader?(u._loading=!0,i=w(u),i.onEnd=N,i.context=u,i.data=e,i.ignoreRegistered=!1,i.require(e),i.insert(null,x?null:"js")):g&&r&&u.Get&&!l.bootstrapped?(u._loading=!0,s=function(){u._loading=!1,p.running=!1,l.bootstrapped=!0,a._bootstrapping=!1,u._attach(["loader"])&&u._use(e,t)},a._bootstrapping?p.add(s):(a._bootstrapping=!0,u.Get.script(m.base+m.loaderPath,{onEnd:s}))):(S=u._attach(e),S&&N()),u},namespace:function(){var e=arguments,t,n=0,i,s,o;for(;n<e.length;n++){t=this,o=e[n];if(o.indexOf(r)>-1){s=o.split(r);for(i=s[0]=="YAHOO"?1:0;i<s.length;i++)t[s[i]]=t[s[i]]||{},t=t[s[i]]}else t[o]=t[o]||{},t=t[o]}return t},log:u,message:u,dump:function(e){return""+e},error:function(e,t,n){var r=this,i;r.config.errorFn&&(i=r.config.errorFn.apply(r,arguments));if(!i)throw t||new Error(e);return r.message(e,"error",""+n),r},guid:function(e){var t=this.Env._guidp+"_"+ ++this.Env._uidx;return e?e+t:t},stamp:function(e,t){var n;if(!e)return e;e.uniqueID&&e.nodeType&&e.nodeType!==9?n=e.uniqueID:n=typeof e=="string"?e:e._yuid;if(!n){n=this.guid();if(!t)try{e._yuid=n}catch(r){n=null}}return n},destroy:function(){var e=this;e.Event&&e.Event._unload(),delete v[e.id],delete e.Env,delete e.config}},YUI.prototype=e;for(t in e)e.hasOwnProperty(t)&&(YUI[t]=e[t]);YUI.applyConfig=function(e){if(!e)return;YUI.GlobalConfig&&this.prototype.applyConfig.call(this,YUI.GlobalConfig),this.prototype.applyConfig.call(this,e),YUI.GlobalConfig=this.config},YUI._init(),l?g(window,"load",b):b(),YUI.Env.add=g,YUI.Env.remove=y,typeof exports=="object"&&(exports.YUI=YUI)})(),YUI.add("yui-base",function(e,t){function h(e,t,n){var r,i;t||(t=0);if(n||h.test(e))try{return l.slice.call(e,t)}catch(s){i=[];for(r=e.length;t<r;++t)i.push(e[t]);return i}return[e]}function p(){this._init(),this.add.apply(this,arguments)}var n=e.Lang||(e.Lang={}),r=String.prototype,i=Object.prototype.toString,s={"undefined":"undefined",number:"number","boolean":"boolean",string:"string","[object Function]":"function","[object RegExp]":"regexp","[object Array]":"array","[object Date]":"date","[object Error]":"error"},o=/\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,u=/^\s+|\s+$/g,a=/\{\s*\[(?:native code|function)\]\s*\}/i;n._isNative=function(t){return!!(e.config.useNativeES5&&t&&a.test(t))},n.isArray=n._isNative(Array.isArray)?Array.isArray:function(e){return n.type(e)==="array"},n.isBoolean=function(e){return typeof e=="boolean"},n.isDate=function(e){return n.type(e)==="date"&&e.toString()!=="Invalid Date"&&!isNaN(e)},n.isFunction=function(e){return n.type(e)==="function"},n.isNull=function(e){return e===null},n.isNumber=function(e){return typeof e=="number"&&isFinite(e)},n.isObject=function(e,t){var r=typeof e;return e&&(r==="object"||!t&&(r==="function"||n.isFunction(e)))||!1},n.isString=function(e){return typeof e=="string"},n.isUndefined=function(e){return typeof e=="undefined"},n.isValue=function(e){var t=n.type(e);switch(t){case"number":return isFinite(e);case"null":case"undefined":return!1;default:return!!t}},n.now=Date.now||function(){return(new Date).getTime()},n.sub=function(e,t){return e.replace?e.replace(o,function(e,r){return n.isUndefined(t[r])?e:t[r]}):e},n.trim=r.trim?function(e){return e&&e.trim?e.trim():e}:function(e){try{return e.replace(u,"")}catch(t){return e}},n.trimLeft=r.trimLeft?function(e){return e.trimLeft()}:function(e){return e.replace(/^\s+/,"")},n.trimRight=r.trimRight?function(e){return e.trimRight()}:function(e){return e.replace(/\s+$/,"")},n.type=function(e){return s[typeof e]||s[i.call(e)]||(e?"object":"null")};var f=e.Lang,l=Array.prototype,c=Object.prototype.hasOwnProperty;e.Array=h,h.dedupe=function(e){var t={},n=[],r,i,s;for(r=0,s=e.length;r<s;++r)i=e[r],c.call(t,i)||(t[i]=1,n.push(i));return n},h.each=h.forEach=f._isNative(l.forEach)?function(t,n,r){return l.forEach.call(t||[],n,r||e),e}:function(t,n,r){for(var i=0,s=t&&t.length||0;i<s;++i)i in t&&n.call(r||e,t[i],i,t);return e},h.hash=function(e,t){var n={},r=t&&t.length||0,i,s;for(i=0,s=e.length;i<s;++i)i in e&&(n[e[i]]=r>i&&i in t?t[i]:!0);return n},h.indexOf=f._isNative(l.indexOf)?function(e,t,n){return l.indexOf.call(e,t,n)}:function(e,t,n){var r=e.length;n=+n||0,n=(n>0||-1)*Math.floor(Math.abs(n)),n<0&&(n+=r,n<0&&(n=0));for(;n<r;++n)if(n in e&&e[n]===t)return n;return-1},h.numericSort=function(e,t){return e-t},h.some=f._isNative(l.some)?function(e,t,n){return l.some.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&t.call(n,e[r],r,e))return!0;return!1},h.test=function(e){var t=0;if(f.isArray(e))t=1;else if(f.isObject(e))try{"length"in e&&!e.tagName&&(!e.scrollTo||!e.document)&&!e.apply&&(t=2)}catch(n){}return t},p.prototype={_init:function(){this._q=[]},next:function(){return this._q.shift()},last:function(){return this._q.pop()},add:function(){return this._q.push.apply(this._q,arguments),this},size:function(){return this._q.length}},e.Queue=p,YUI.Env._loaderQueue=YUI.Env._loaderQueue||new p;var d="__",c=Object.prototype.hasOwnProperty,v=e.Lang.isObject;e.cached=function(e,t,n){return t||(t={}),function(r){var i=arguments.length>1?Array.prototype.join.call(arguments,d):String(r);if(!(i in t)||n&&t[i]==n)t[i]=e.apply(e,arguments);return t[i]}},e.getLocation=function(){var t=e.config.win;return t&&t.location},e.merge=function(){var e=0,t=arguments.length,n={},r,i;for(;e<t;++e){i=arguments[e];for(r in i)c.call(i,r)&&(n[r]=i[r])}return n},e.mix=function(t,n,r,i,s,o){var u,a,f,l,h,p,d;if(!t||!n)return t||e;if(s){s===2&&e.mix(t.prototype,n.prototype,r,i,0,o),f=s===1||s===3?n.prototype:n,d=s===1||s===4?t.prototype:t;if(!f||!d)return t}else f=n,d=t;u=r&&!o;if(i)for(l=0,p=i.length;l<p;++l){h=i[l];if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}else{for(h in f){if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}e.Object._hasEnumBug&&e.mix(d,f,r,e.Object._forceEnum,s,o)}return t};var f=e.Lang,c=Object.prototype.hasOwnProperty,m,g=e.Object=f._isNative(Object.create)?function(e){return Object.create(e)}:function(){function e(){}return function(t){return e.prototype=t,new e}}(),y=g._forceEnum=["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf"],b=g._hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),w=g._hasProtoEnumBug=function(){}.propertyIsEnumerable("prototype"),E=g.owns=function(e,t){return!!e&&c.call(e,t)};g.hasKey=E,g.keys=f._isNative(Object.keys)?Object.keys:function(e){if(!f.isObject(e))throw new TypeError("Object.keys called on a non-object");var t=[],n,r,i;if(w&&typeof e=="function")for(r in e)E(e,r)&&r!=="prototype"&&t.push(r);else for(r in e)E(e,r)&&t.push(r);if(b)for(n=0,i=y.length;n<i;++n)r=y[n],E(e,r)&&t.push(r);return t},g.values=function(e){var t=g.keys(e),n=0,r=t.length,i=[];for(;n<r;++n)i.push(e[t[n]]);return i},g.size=function(e){try{return g.keys(e).length}catch(t){return 0}},g.hasValue=function(t,n){return e.Array.indexOf(g.values(t),n)>-1},g.each=function(t,n,r,i){var s;for(s in t)(i||E(t,s))&&n.call(r||e,t[s],s,t);return e},g.some=function(t,n,r,i){var s;for(s in t)if(i||E(t,s))if(n.call(r||e,t[s],s,t))return!0;return!1},g.getValue=function(t,n){if(!f.isObject(t))return m;var r,i=e.Array(n),s=i.length;for(r=0;t!==m&&r<s;r++)t=t[i[r]];return t},g.setValue=function(t,n,r){var i,s=e.Array(n),o=s.length-1,u=t;if(o>=0){for(i=0;u!==m&&i<o;i++)u=u[s[i]];if(u===m)return m;u[s[i]]=r}return t},g.isEmpty=function(e){return!g.keys(Object(e)).length},YUI.Env.parseUA=function(t){var n=function(e){var t=0;return parseFloat(e.replace(/\./g,function(){return t++===1?"":"."}))},r=e.config.win,i=r&&r.navigator,s={ie:0,opera:0,gecko:0,webkit:0,safari:0,chrome:0,mobile:null,air:0,phantomjs:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,silk:0,accel:!1,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null,nodejs:0,winjs:typeof Windows!="undefined"&&!!Windows.System,touchEnabled:!1},o=t||i&&i.userAgent,u=r&&r.location,a=u&&u.href,f;return s.userAgent=o,s.secure=a&&a.toLowerCase().indexOf("https")===0,o&&(/windows|win32/i.test(o)?s.os="windows":/macintosh|mac_powerpc/i.test(o)?s.os="macintosh":/android/i.test(o)?s.os="android":/symbos/i.test(o)?s.os="symbos":/linux/i.test(o)?s.os="linux":/rhino/i.test(o)&&(s.os="rhino"),/KHTML/.test(o)&&(s.webkit=1),/IEMobile|XBLWP7/.test(o)&&(s.mobile="windows"),/Fennec/.test(o)&&(s.mobile="gecko"),f=o.match(/AppleWebKit\/([^\s]*)/),f&&f[1]&&(s.webkit=n(f[1]),s.safari=s.webkit,/PhantomJS/.test(o)&&(f=o.match(/PhantomJS\/([^\s]*)/),f&&f[1]&&(s.phantomjs=n(f[1]))),/ Mobile\//.test(o)||/iPad|iPod|iPhone/.test(o)?(s.mobile="Apple",f=o.match(/OS ([^\s]*)/),f&&f[1]&&(f=n(f[1].replace("_","."))),s.ios=f,s.os="ios",s.ipad=s.ipod=s.iphone=0,f=o.match(/iPad|iPod|iPhone/),f&&f[0]&&(s[f[0].toLowerCase()]=s.ios)):(f=o.match(/NokiaN[^\/]*|webOS\/\d\.\d/),f&&(s.mobile=f[0]),/webOS/.test(o)&&(s.mobile="WebOS",f=o.match(/webOS\/([^\s]*);/),f&&f[1]&&(s.webos=n(f[1]))),/ Android/.test(o)&&(/Mobile/.test(o)&&(s.mobile="Android"),f=o.match(/Android ([^\s]*);/),f&&f[1]&&(s.android=n(f[1]))),/Silk/.test(o)&&(f=o.match(/Silk\/([^\s]*)\)/),f&&f[1]&&(s.silk=n(f[1])),s.android||(s.android=2.34,s.os="Android"),/Accelerated=true/.test(o)&&(s.accel=!0))),f=o.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/),f&&f[1]&&f[2]?(s.chrome=n(f[2]),s.safari=0,f[1]==="CrMo"&&(s.mobile="chrome")):(f=o.match(/AdobeAIR\/([^\s]*)/),f&&(s.air=f[0]))),s.webkit||(/Opera/.test(o)?(f=o.match(/Opera[\s\/]([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),f=o.match(/Version\/([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),/Opera Mobi/.test(o)&&(s.mobile="opera",f=o.replace("Opera Mobi","").match(/Opera ([^\s]*)/),f&&f[1]&&(s.opera=n(f[1]))),f=o.match(/Opera Mini[^;]*/),f&&(s.mobile=f[0])):(f=o.match(/MSIE\s([^;]*)/),f&&f[1]?s.ie=n(f[1]):(f=o.match(/Gecko\/([^\s]*)/),f&&(s.gecko=1,f=o.match(/rv:([^\s\)]*)/),f&&f[1]&&(s.gecko=n(f[1]))))))),r&&i&&!(s.chrome&&s.chrome<6)&&(s.touchEnabled="ontouchstart"in r||"msMaxTouchPoints"in i&&i.msMaxTouchPoints>0),t||(typeof process=="object"&&process.versions&&process.versions.node&&(s.os=process.platform,s.nodejs=n(process.versions.node)),YUI.Env.UA=s),s},e.UA=YUI.Env.UA||YUI.Env.parseUA(),e.UA.compareVersions=function(e,t){var n,r,i,s,o,u;if(e===t)return 0;r=(e+"").split("."),s=(t+"").split(".");for(o=0,u=Math.max(r.length,s.length);o<u;++o){n=parseInt(r[o],10),i=parseInt(s[o],10),isNaN(n)&&(n=0),isNaN(i)&&(i=0);if(n<i)return-1;if(n>i)return 1}return 0},YUI.Env.aliases={anim:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],"anim-shape-transform":["anim-shape"],app:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],attribute:["attribute-base","attribute-complex"],autocomplete:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],base:["base-base","base-pluginhost","base-build"],cache:["cache-base","cache-offline","cache-plugin"],collection:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],controller:["router"],dataschema:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],datasource:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],datatable:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],"datatable-deprecated":["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],datatype:["datatype-date","datatype-number","datatype-xml"],"datatype-date":["datatype-date-parse","datatype-date-format","datatype-date-math"],"datatype-number":["datatype-number-parse","datatype-number-format"],"datatype-xml":["datatype-xml-parse","datatype-xml-format"],dd:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],dom:["dom-base","dom-screen","dom-style","selector-native","selector"],editor:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],event:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],"event-custom":["event-custom-base","event-custom-complex"],"event-gestures":["event-flick","event-move"],handlebars:["handlebars-compiler"],highlight:["highlight-base","highlight-accentfold"],history:["history-base","history-hash","history-hash-ie","history-html5"],io:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],json:["json-parse","json-stringify"],loader:["loader-base","loader-rollup","loader-yui3"],node:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],pluginhost:["pluginhost-base","pluginhost-config"],querystring:["querystring-parse","querystring-stringify"],recordset:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],resize:["resize-base","resize-proxy","resize-constrain"],slider:["slider-base","slider-value-range","clickable-rail","range-slider"],text:["text-accentfold","text-wordbreak"],widget:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]}},"3.7.3",{use:["get","features","intl-base","yui-log","yui-later"]}),YUI.add("get",function(e,t){var n=e.Lang,r,i,s;e.Get=i={cssOptions:{attributes:{rel:"stylesheet"},doc:e.config.linkDoc||e.config.doc,pollInterval:50},jsOptions:{autopurge:!0,doc:e.config.scriptDoc||e.config.doc},options:{attributes:{charset:"utf-8"},purgethreshold:20},REGEX_CSS:/\.css(?:[?;].*)?$/i,REGEX_JS:/\.js(?:[?;].*)?$/i,_insertCache:{},_pending:null,_purgeNodes:[],_queue:[],abort:function(e){var t,n,r,i,s;if(!e.abort){n=e,s=this._pending,e=null;if(s&&s.transaction.id===n)e=s.transaction,this._pending=null;else for(t=0,i=this._queue.length;t<i;++t){r=this._queue[t].transaction;if(r.id===n){e=r,this._queue.splice(t,1);break}}}e&&e.abort()},css:function(e,t,n){return this._load("css",e,t,n)},js:function(e,t,n){return this._load("js",e,t,n)},load:function(e,t,n){return this._load(null,e,t,n)},_autoPurge:function(e){e&&this._purgeNodes.length>=e&&this._purge(this._purgeNodes)},_getEnv:function(){var t=e.config.doc,n=e.UA;return this._env={async:t&&t.createElement("script").async===!0||n.ie>=10,cssFail:n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0,cssLoad:(!n.gecko&&!n.webkit||n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0)&&!(n.chrome&&n.chrome<=18),preservesScriptOrder:!!(n.gecko||n.opera||n.ie&&n.ie>=10)}},_getTransaction:function(t,r){var i=[],o,u,a,f;n.isArray(t)||(t=[t]),r=e.merge(this.options,r),r.attributes=e.merge(this.options.attributes,r.attributes);for(o=0,u=t.length;o<u;++o){f=t[o],a={attributes:{}};if(typeof f=="string")a.url=f;else{if(!f.url)continue;e.mix(a,f,!1,null,0,!0),f=f.url}e.mix(a,r,!1,null,0,!0),a.type||(this.REGEX_CSS.test(f)?a.type="css":(!this.REGEX_JS.test(f),a.type="js")),e.mix(a,a.type==="js"?this.jsOptions:this.cssOptions,!1,null,0,!0),a.attributes.id||(a.attributes.id=e.guid()),a.win?a.doc=a.win.document:a.win=a.doc.defaultView||a.doc.parentWindow,a.charset&&(a.attributes.charset=a.charset),i.push(a)}return new s(i,r)},_load:function(e,t,n,r){var s;return typeof n=="function"&&(r=n,n={}),n||(n={}),n.type=e,n._onFinish=i._onTransactionFinish,this._env||this._getEnv(),s=this._getTransaction(t,n),this._queue.push({callback:r,transaction:s}),this._next(),s},_onTransactionFinish:function(){i._pending=null,i._next()},_next:function(){var e;if(this._pending)return;e=this._queue.shift(),e&&(this._pending=e,e.transaction.execute(e.callback))},_purge:function(t){var n=this._purgeNodes,r=t!==n,i,s;while(s=t.pop()){if(!s._yuiget_finished)continue;s.parentNode&&s.parentNode.removeChild(s),r&&(i=e.Array.indexOf(n,s),i>-1&&n.splice(i,1))}}},i.script=i.js,i.Transaction=s=function(t,n){var r=this;r.id=s._lastId+=1,r.data=n.data,r.errors=[],r.nodes=[],r.options=n,r.requests=t,r._callbacks=[],r._queue=[],r._reqsWaiting=0,r.tId=r.id,r.win=n.win||e.config.win},s._lastId=0,s.prototype={_state:"new",abort:function(e){this._pending=null,this._pendingCSS=null,this._pollTimer=clearTimeout(this._pollTimer),this._queue=[],this._reqsWaiting=0,this.errors.push({error:e||"Aborted"}),this._finish()},execute:function(e){var t=this,n=t.requests,r=t._state,i,s,o,u;if(r==="done"){e&&e(t.errors.length?t.errors:null,t);return}e&&t._callbacks.push(e);if(r==="executing")return;t._state="executing",t._queue=o=[],t.options.timeout&&(t._timeout=setTimeout(function(){t.abort("Timeout")},t.options.timeout)),t._reqsWaiting=n.length;for(i=0,s=n.length;i<s;++i)u=n[i],u.async||u.type==="css"?t._insert(u):o.push(u);t._next()},purge:function(){i._purge(this.nodes)},_createNode:function(e,t,n){var i=n.createElement(e),s,o;r||(o=n.createElement("div"),o.setAttribute("class","a"),r=o.className==="a"?{}:{"for":"htmlFor","class":"className"});for(s in t)t.hasOwnProperty(s)&&i.setAttribute(r[s]||s,t[s]);return i},_finish:function(){var e=this.errors.length?this.errors:null,t=this.options,n=t.context||this,r,i,s;if(this._state==="done")return;this._state="done";for(i=0,s=this._callbacks.length;i<s;++i)this._callbacks[i].call(n,e,this);r=this._getEventData(),e?(t.onTimeout&&e[e.length-1].error==="Timeout"&&t.onTimeout.call(n,r),t.onFailure&&t.onFailure.call(n,r)):t.onSuccess&&t.onSuccess.call(n,r),t.onEnd&&t.onEnd.call(n,r),t._onFinish&&t._onFinish()},_getEventData:function(t){return t?e.merge(this,{abort:this.abort,purge:this.purge,request:t,url:t.url,win:t.win}):this},_getInsertBefore:function(t){var n=t.doc,r=t.insertBefore,s,o,u;return r?typeof r=="string"?n.getElementById(r):r:(s=i._insertCache,u=e.stamp(n),(r=s[u])?r:(r=n.getElementsByTagName("base")[0])?s[u]=r:(r=n.head||n.getElementsByTagName("head")[0],r?(r.appendChild(n.createTextNode("")),s[u]=r.lastChild):s[u]=n.getElementsByTagName("script")[0]))},_insert:function(t){function c(){u._progress("Failed to load "+t.url,t)}function h(){f&&clearTimeout(f),u._progress(null,t)}var n=i._env,r=this._getInsertBefore(t),s=t.type==="js",o=t.node,u=this,a=e.UA,f,l;o||(s?l="script":!n.cssLoad&&a.gecko?l="style":l="link",o=t.node=this._createNode(l,t.attributes,t.doc)),s?(o.setAttribute("src",t.url),t.async?o.async=!0:(n.async&&(o.async=!1),n.preservesScriptOrder||(this._pending=t))):!n.cssLoad&&a.gecko?o.innerHTML=(t.attributes.charset?'@charset "'+t.attributes.charset+'";':"")+'@import "'+t.url+'";':o.setAttribute("href",t.url),s&&a.ie&&(a.ie<9||document.documentMode&&document.documentMode<9)?o.onreadystatechange=function(){/loaded|complete/.test(o.readyState)&&(o.onreadystatechange=null,h())}:!s&&!n.cssLoad?this._poll(t):(a.ie>=10?(o.onerror=function(){setTimeout(c,0)},o.onload=function(){setTimeout(h,0)}):(o.onerror=c,o.onload=h),!n.cssFail&&!s&&(f=setTimeout(c,t.timeout||3e3))),this.nodes.push(o),r.parentNode.insertBefore(o,r)},_next:function(){if(this._pending)return;this._queue.length?this._insert(this._queue.shift()):this._reqsWaiting||this._finish()},_poll:function(t){var n=this,r=n._pendingCSS,i=e.UA.webkit,s,o,u,a,f,l;if(t){r||(r=n._pendingCSS=[]),r.push(t);if(n._pollTimer)return}n._pollTimer=null;for(s=0;s<r.length;++s){f=r[s];if(i){l=f.doc.styleSheets,u=l.length,a=f.node.href;while(--u>=0)if(l[u].href===a){r.splice(s,1),s-=1,n._progress(null,f);break}}else try{o=!!f.node.sheet.cssRules,r.splice(s,1),s-=1,n._progress(null,f)}catch(c){}}r.length&&(n._pollTimer=setTimeout(function(){n._poll.call(n)},n.options.pollInterval))},_progress:function(e,t){var n=this.options;e&&(t.error=e,this.errors.push({error:e,request:t})),t.node._yuiget_finished=t.finished=!0,n.onProgress&&n.onProgress.call(n.context||this,this._getEventData(t)),t.autopurge&&(i._autoPurge(this.options.purgethreshold),i._purgeNodes.push(t.node)),this._pending===t&&(this._pending=null),this._reqsWaiting-=1,this._next()}}},"3.7.3",{requires:["yui-base"]}),YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]}),YUI.add("intl-base",function(e,t){var n=/[, ]/;e.mix(e.namespace("Intl"),{lookupBestLang:function(t,r){function a(e){var t;for(t=0;t<r.length;t+=1)if(e.toLowerCase()===r[t].toLowerCase())return r[t]}var i,s,o,u;e.Lang.isString(t)&&(t=t.split(n));for(i=0;i<t.length;i+=1){s=t[i];if(!s||s==="*")continue;while(s.length>0){o=a(s);if(o)return o;u=s.lastIndexOf("-");if(!(u>=0))break;s=s.substring(0,u),u>=2&&s.charAt(u-2)==="-"&&(s=s.substring(0,u-2))}}return""}})},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-later",function(e,t){var n=[];e.later=function(t,r,i,s,o){t=t||0,s=e.Lang.isUndefined(s)?n:e.Array(s),r=r||e.config.win||e;var u=!1,a=r&&e.Lang.isString(i)?r[i]:i,f=function(){u||(a.apply?a.apply(r,s||n):a(s[0],s[1],s[2],s[3]))},l=o?setInterval(f,t):setTimeout(f,t);return{id:l,interval:o,cancel:function(){u=!0,this.interval?clearInterval(l):clearTimeout(l)}}},e.Lang.later=e.later},"3.7.3",{requires:["yui-base"]}),YUI.add("yui",function(e,t){},"3.7.3",{use:["get","features","intl-base","yui-log","yui-later"]}),YUI.add("oop",function(e,t){function a(t,n,i,s,o){if(t&&t[o]&&t!==e)return t[o].call(t,n,i);switch(r.test(t)){case 1:return r[o](t,n,i);case 2:return r[o](e.Array(t,0,!0),n,i);default:return e.Object[o](t,n,i,s)}}var n=e.Lang,r=e.Array,i=Object.prototype,s="_~yuim~_",o=i.hasOwnProperty,u=i.toString;e.augment=function(t,n,r,i,s){var a=t.prototype,f=a&&n,l=n.prototype,c=a||t,h,p,d,v,m;return s=s?e.Array(s):[],f&&(p={},d={},v={},h=function(e,t){if(r||!(t in a))u.call(e)==="[object Function]"?(v[t]=e,p[t]=d[t]=function(){return m(this,e,arguments)}):p[t]=e},m=function(e,t,r){for(var i in v)o.call(v,i)&&e[i]===d[i]&&(e[i]=v[i]);return n.apply(e,s),t.apply(e,r)},i?e.Array.each(i,function(e){e in l&&h(l[e],e)}):e.Object.each(l,h,null,!0)),e.mix(c,p||l,r,i),f||n.apply(c,s),t},e.aggregate=function(t,n,r,i){return e.mix(t,n,r,i,0,!0)},e.extend=function(t,n,r,s){(!n||!t)&&e.error("extend failed, verify dependencies");var o=n.prototype,u=e.Object(o);return t.prototype=u,u.constructor=t,t.superclass=o,n!=Object&&o.constructor==i.constructor&&(o.constructor=n),r&&e.mix(u,r,!0),s&&e.mix(t,s,!0),t},e.each=function(e,t,n,r){return a(e,t,n,r,"each")},e.some=function(e,t,n,r){return a(e,t,n,r,"some")},e.clone=function(t,r,i,o,u,a){if(!n.isObject(t))return t;if(e.instanceOf(t,YUI))return t;var f,l=a||{},c,h=e.each;switch(n.type(t)){case"date":return new Date(t);case"regexp":return t;case"function":return t;case"array":f=[];break;default:if(t[s])return l[t[s]];c=e.guid(),f=r?{}:e.Object(t),t[s]=c,l[c]=t}return!t.addEventListener&&!t.attachEvent&&h(t,function(n,a){(a||a===0)&&(!i||i.call(o||this,n,a,this,t)!==!1)&&a!==s&&a!="prototype"&&(this[a]=e.clone(n,r,i,o,u||t,l))},f),a||(e.Object.each(l,function(e,t){if(e[s])try{delete e[s]}catch(n){e[s]=null}},this),l=null),f},e.bind=function(t,r){var i=arguments.length>2?e.Array(arguments,2,!0):null;return function(){var s=n.isString(t)?r[t]:t,o=i?i.concat(e.Array(arguments,0,!0)):arguments;return s.apply(r||s,o)}},e.rbind=function(t,r){var i=arguments.length>2?e.Array(arguments,2,!0):null;return function(){var s=n.isString(t)?r[t]:t,o=i?e.Array(arguments,0,!0).concat(i):arguments;return s.apply(r||s,o)}}},"3.7.3",{requires:["yui-base"]}),YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]}),YUI.add("dom-core",function(e,t){var n="nodeType",r="ownerDocument",i="documentElement",s="defaultView",o="parentWindow",u="tagName",a="parentNode",f="previousSibling",l="nextSibling",c="contains",h="compareDocumentPosition",p=[],d=function(){var t=e.config.doc.createElement("div"),n=t.appendChild(e.config.doc.createTextNode("")),r=!1;try{r=t.contains(n)}catch(i){}return r}(),v={byId:function(e,t){return v.allById(e,t)[0]||null},getId:function(e){var t;return e.id&&!e.id.tagName&&!e.id.item?t=e.id:e.attributes&&e.attributes.id&&(t=e.attributes.id.value),t},setId:function(e,t){e.setAttribute?e.setAttribute("id",t):e.id=t},ancestor:function(e,t,n,r){var i=null;return n&&(i=!t||t(e)?e:null),i||v.elementByAxis(e,a,t,null,r)},ancestors:function(e,t,n,r){var i=e,s=[];while(i=v.ancestor(i,t,n,r)){n=!1;if(i){s.unshift(i);if(r&&r(i))return s}}return s},elementByAxis:function(e,t,n,r,i){while(e&&(e=e[t])){if((r||e[u])&&(!n||n(e)))return e;if(i&&i(e))return null}return null},contains:function(e,t){var r=!1;if(!t||!e||!t[n]||!e[n])r=!1;else if(e[c]&&(t[n]===1||d))r=e[c](t);else if(e[h]){if(e===t||!!(e[h](t)&16))r=!0}else r=v._bruteContains(e,t);return r},inDoc:function(e,t){var n=!1,s;return e&&e.nodeType&&(t||(t=e[r]),s=t[i],s&&s.contains&&e.tagName?n=s.contains(e):n=v.contains(s,e)),n},allById:function(t,n){n=n||e.config.doc;var r=[],i=[],s,o;if(n.querySelectorAll)i=n.querySelectorAll('[id="'+t+'"]');else if(n.all){r=n.all(t);if(r){r.nodeName&&(r.id===t?(i.push(r),r=p):r=[r]);if(r.length)for(s=0;o=r[s++];)(o.id===t||o.attributes&&o.attributes.id&&o.attributes.id.value===t)&&i.push(o)}}else i=[v._getDoc(n).getElementById(t)];return i},isWindow:function(e){return!!(e&&e.scrollTo&&e.document)},_removeChildNodes:function(e){while(e.firstChild)e.removeChild(e.firstChild)},siblings:function(e,t){var n=[],r=e;while(r=r[f])r[u]&&(!t||t(r))&&n.unshift(r);r=e;while(r=r[l])r[u]&&(!t||t(r))&&n.push(r);return n},_bruteContains:function(e,t){while(t){if(e===t)return!0;t=t.parentNode}return!1},_getRegExp:function(e,t){return t=t||"",v._regexCache=v._regexCache||{},v._regexCache[e+t]||(v._regexCache[e+t]=new RegExp(e,t)),v._regexCache[e+t]},_getDoc:function(t){var i=e.config.doc;return t&&(i=t[n]===9?t:t[r]||t.document||e.config.doc),i},_getWin:function(t){var n=v._getDoc(t);return n[s]||n[o]||e.config.win},_batch:function(e,t,n,r,i,s){t=typeof t=="string"?v[t]:t;var o,u=0,a,f;if(t&&e)while(a=e[u++])o=o=t.call(v,a,n,r,i,s),typeof o!="undefined"&&(f||(f=[]),f.push(o));return typeof f!="undefined"?f:e},generateID:function(t){var n=t.id;return n||(n=e.stamp(t),t.id=n),n}};e.DOM=v},"3.7.3",{requires:["oop","features"]}),YUI.add("dom-base",function(e,t){var n=e.config.doc.documentElement,r=e.DOM,i="tagName",s="ownerDocument",o="",u=e.Features.add,a=e.Features.test;e.mix(r,{getText:n.textContent!==undefined?function(e){var t="";return e&&(t=e.textContent),t||""}:function(e){var t="";return e&&(t=e.innerText||e.nodeValue),t||""},setText:n.textContent!==undefined?function(e,t){e&&(e.textContent=t)}:function(e,t){"innerText"in e?e.innerText=t:"nodeValue"in e&&(e.nodeValue=t)},CUSTOM_ATTRIBUTES:n.hasAttribute?{htmlFor:"for",className:"class"}:{"for":"htmlFor","class":"className"},setAttribute:function(e,t,n,i){e&&t&&e.setAttribute&&(t=r.CUSTOM_ATTRIBUTES[t]||t,e.setAttribute(t,n,i))},getAttribute:function(e,t,n){n=n!==undefined?n:2;var i="";return e&&t&&e.getAttribute&&(t=r.CUSTOM_ATTRIBUTES[t]||t,i=e.getAttribute(t,n),i===null&&(i="")),i},VALUE_SETTERS:{},VALUE_GETTERS:{},getValue:function(e){var t="",n;return e&&e[i]&&(n=r.VALUE_GETTERS[e[i].toLowerCase()],n?t=n(e):t=e.value),t===o&&(t=o),typeof t=="string"?t:""},setValue:function(e,t){var n;e&&e[i]&&(n=r.VALUE_SETTERS[e[i].toLowerCase()],n?n(e,t):e.value=t)},creators:{}}),u("value-set","select",{test:function(){var t=e.config.doc.createElement("select");return t.innerHTML="<option>1</option><option>2</option>",t.value="2",t.value&&t.value==="2"}}),a("value-set","select")||(r.VALUE_SETTERS.select=function(e,t){for(var n=0,i=e.getElementsByTagName("option"),s;s=i[n++];)if(r.getValue(s)===t){s.selected=!0;break}}),e.mix(r.VALUE_GETTERS,{button:function(e){return e.attributes&&e.attributes.value?e.attributes.value.value:""}}),e.mix(r.VALUE_SETTERS,{button:function(e,t){var n=e.attributes.value;n||(n=e[s].createAttribute("value"),e.setAttributeNode(n)),n.value=t}}),e.mix(r.VALUE_GETTERS,{option:function(e){var t=e.attributes;return t.value&&t.value.specified?e.value:e.text},select:function(e){var t=e.value,n=e.options;return n&&n.length&&(e.multiple||e.selectedIndex>-1&&(t=r.getValue(n[e.selectedIndex]))),t}});var f,l,c;e.mix(e.DOM,{hasClass:function(t,n){var r=e.DOM._getRegExp("(?:^|\\s+)"+n+"(?:\\s+|$)");return r.test(t.className)},addClass:function(t,n){e.DOM.hasClass(t,n)||(t.className=e.Lang.trim([t.className,n].join(" ")))},removeClass:function(t,n){n&&l(t,n)&&(t.className=e.Lang.trim(t.className.replace(e.DOM._getRegExp("(?:^|\\s+)"+n+"(?:\\s+|$)")," ")),l(t,n)&&c(t,n))},replaceClass:function(e,t,n){c(e,t),f(e,n)},toggleClass:function(e,t,n){var r=n!==undefined?n:!l(e,t);r?f(e,t):c(e,t)}}),l=e.DOM.hasClass,c=e.DOM.removeClass,f=e.DOM.addClass;var h=/<([a-z]+)/i,r=e.DOM,u=e.Features.add,a=e.Features.test,p={},d=function(t,n){var r=e.config.doc.createElement("div"),i=!0;r.innerHTML=t;if(!r.firstChild||r.firstChild.tagName!==n.toUpperCase())i=!1;return i},v=/(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,m="<table>",g="</table>";e.mix(e.DOM,{_fragClones:{},_create:function(e,t,n){n=n||"div";var i=r._fragClones[n];return i?i=i.cloneNode(!1):i=r._fragClones[n]=t.createElement(n),i.innerHTML=e,i},_children:function(e,t){var n=0,r=e.children,i,s,o;r&&r.tags&&(t?r=e.children.tags(t):s=r.tags("!").length);if(!r||!r.tags&&t||s){i=r||e.childNodes,r=[];while(o=i[n++])o.nodeType===1&&(!t||t===o.tagName)&&r.push(o)}return r||[]},create:function(t,n){typeof t=="string"&&(t=e.Lang.trim(t)),n=n||e.config.doc;var i=h.exec(t),s=r._create,o=p,u=null,a,f,l;return t!=undefined&&(i&&i[1]&&(a=o[i[1].toLowerCase()],typeof a=="function"?s=a:f=a),l=s(t,n,f).childNodes,l.length===1?u=l[0].parentNode.removeChild(l[0]):l[0]&&l[0].className==="yui3-big-dummy"?l.length===2?u=l[0].nextSibling:(l[0].parentNode.removeChild(l[0]),u=r._nl2frag(l,n)):u=r._nl2frag(l,n)),u},_nl2frag:function(t,n){var r=null,i,s;if(t&&(t.push||t.item)&&t[0]){n=n||t[0].ownerDocument,r=n.createDocumentFragment(),t.item&&(t=e.Array(t,0,!0));for(i=0,s=t.length;i<s;i++)r.appendChild(t[i])}return r},addHTML:function(t,n,i){var s=t.parentNode,o=0,u,a=n,f;if(n!=undefined)if(n.nodeType)f=n;else if(typeof n=="string"||typeof n=="number")a=f=r.create(n);else if(n[0]&&n[0].nodeType){f=e.config.doc.createDocumentFragment();while(u=n[o++])f.appendChild(u)}if(i)if(f&&i.parentNode)i.parentNode.insertBefore(f,i);else switch(i){case"replace":while(t.firstChild)t.removeChild(t.firstChild);f&&t.appendChild(f);break;case"before":f&&s.insertBefore(f,t);break;case"after":f&&(t.nextSibling?s.insertBefore(f,t.nextSibling):s.appendChild(f));break;default:f&&t.appendChild(f)}else f&&t.appendChild(f);return a},wrap:function(t,n){var r=n&&n.nodeType?n:e.DOM.create(n),i=r.getElementsByTagName("*");i.length&&(r=i[i.length-1]),t.parentNode&&t.parentNode.replaceChild(r,t),r.appendChild(t)},unwrap:function(e){var t=e.parentNode,n=t.lastChild,r=e,i;if(t){i=t.parentNode;if(i){e=t.firstChild;while(e!==n)r=e.nextSibling,i.insertBefore(e,t),e=r;i.replaceChild(n,t)}else t.removeChild(e)}}}),u("innerhtml","table",{test:function(){var t=e.config.doc.createElement("table");try{t.innerHTML="<tbody></tbody>"}catch(n){return!1}return t.firstChild&&t.firstChild.nodeName==="TBODY"}}),u("innerhtml-div","tr",{test:function(){return d("<tr></tr>","tr")}}),u("innerhtml-div","script",{test:function(){return d("<script></script>","script")}}),a("innerhtml","table")||(p.tbody=function(t,n){var i=r.create(m+t+g,n),s=e.DOM._children(i,"tbody")[0];return i.children.length>1&&s&&!v.test(t)&&s.parentNode.removeChild(s),i}),a("innerhtml-div","script")||(p.script=function(e,t){var n=t.createElement("div");return n.innerHTML="-"+e,n.removeChild(n.firstChild),n},p.link=p.style=p.script),a("innerhtml-div","tr")||(e.mix(p,{option:function(e,t){return r.create('<select><option class="yui3-big-dummy" selected></option>'+e+"</select>",t)},tr:function(e,t){return r.create("<tbody>"+e+"</tbody>",t)},td:function(e,t){return r.create("<tr>"+e+"</tr>",t)},col:function(e,t){return r.create("<colgroup>"+e+"</colgroup>",t)},tbody:"table"}),e.mix(p,{legend:"fieldset",th:p.td,thead:p.tbody,tfoot:p.tbody,caption:p.tbody,colgroup:p.tbody,optgroup:p.option})),r.creators=p,e.mix(e.DOM,{setWidth:function(t,n){e.DOM._setSize(t,"width",n)},setHeight:function(t,n){e.DOM._setSize(t,"height",n)},_setSize:function(e,t,n){n=n>0?n:0;var r=0;e.style[t]=n+"px",r=t==="height"?e.offsetHeight:e.offsetWidth,r>n&&(n-=r-n,n<0&&(n=0),e.style[t]=n+"px")}})},"3.7.3",{requires:["dom-core"]}),YUI.add("dom-style",function(e,t){(function(e){var t="documentElement",n="defaultView",r="ownerDocument",i="style",s="float",o="cssFloat",u="styleFloat",a="transparent",f="getComputedStyle",l="getBoundingClientRect",c=e.config.win,h=e.config.doc,p=undefined,d=e.DOM,v="transform",m="transformOrigin",g=["WebkitTransform","MozTransform","OTransform","msTransform"],y=/color$/i,b=/width|height|top|left|right|bottom|margin|padding/i;e.Array.each(g,function(e){e in h[t].style&&(v=e,m=e+"Origin")}),e.mix(d,{DEFAULT_UNIT:"px",CUSTOM_STYLES:{},setStyle:function(e,t,n,r){r=r||e.style;var i=d.CUSTOM_STYLES;if(r){n===null||n===""?n="":!isNaN(new Number(n))&&b.test(t)&&(n+=d.DEFAULT_UNIT);if(t in i){if(i[t].set){i[t].set(e,n,r);return}typeof i[t]=="string"&&(t=i[t])}else t===""&&(t="cssText",n="");r[t]=n}},getStyle:function(e,t,n){n=n||e.style;var r=d.CUSTOM_STYLES,i="";if(n){if(t in r){if(r[t].get)return r[t].get(e,t,n);typeof r[t]=="string"&&(t=r[t])}i=n[t],i===""&&(i=d[f](e,t))}return i},setStyles:function(t,n){var r=t.style;e.each(n,function(e,n){d.setStyle(t,n,e,r)},d)},getComputedStyle:function(e,t){var s="",o=e[r],u;return e[i]&&o[n]&&o[n][f]&&(u=o[n][f](e,null),u&&(s=u[t])),s}}),h[t][i][o]!==p?d.CUSTOM_STYLES[s]=o:h[t][i][u]!==p&&(d.CUSTOM_STYLES[s]=u),e.UA.opera&&(d[f]=function(t,i){var s=t[r][n],o=s[f](t,"")[i];return y.test(i)&&(o=e.Color.toRGB(o)),o}),e.UA.webkit&&(d[f]=function(e,t){var i=e[r][n],s=i[f](e,"")[t];return s==="rgba(0, 0, 0, 0)"&&(s=a),s}),e.DOM._getAttrOffset=function(t,n){var r=e.DOM[f](t,n),i=t.offsetParent,s,o,u;return r==="auto"&&(s=e.DOM.getStyle(t,"position"),s==="static"||s==="relative"?r=0:i&&i[l]&&(o=i[l]()[n],u=t[l]()[n],n==="left"||n==="top"?r=u-o:r=o-t[l]()[n])),r},e.DOM._getOffset=function(e){var t,n=null;return e&&(t=d.getStyle(e,"position"),n=[parseInt(d[f](e,"left"),10),parseInt(d[f](e,"top"),10)],isNaN(n[0])&&(n[0]=parseInt(d.getStyle(e,"left"),10),isNaN(n[0])&&(n[0]=t==="relative"?0:e.offsetLeft||0)),isNaN(n[1])&&(n[1]=parseInt(d.getStyle(e,"top"),10),isNaN(n[1])&&(n[1]=t==="relative"?0:e.offsetTop||0))),n},d.CUSTOM_STYLES.transform={set:function(e,t,n){n[v]=t},get:function(e,t){return d[f](e,v)}},d.CUSTOM_STYLES.transformOrigin={set:function(e,t,n){n[m]=t},get:function(e,t){return d[f](e,m)}}})(e),function(e){var t=parseInt,n=RegExp;e.Color={KEYWORDS:{black:"000",silver:"c0c0c0",gray:"808080",white:"fff",maroon:"800000",red:"f00",purple:"800080",fuchsia:"f0f",green:"008000",lime:"0f0",olive:"808000",yellow:"ff0",navy:"000080",blue:"00f",teal:"008080",aqua:"0ff"},re_RGB:/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,re_hex:/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,re_hex3:/([0-9A-F])/gi,toRGB:function(r){return e.Color.re_RGB.test(r)||(r=e.Color.toHex(r)),e.Color.re_hex.exec(r)&&(r="rgb("+[t(n.$1,16),t(n.$2,16),t(n.$3,16)].join(", ")+")"),r},toHex:function(t){t=e.Color.KEYWORDS[t]||t;if(e.Color.re_RGB.exec(t)){t=[Number(n.$1).toString(16),Number(n.$2).toString(16),Number(n.$3).toString(16)];for(var r=0;r<t.length;r++)t[r].length<2&&(t[r]="0"+t[r]);t=t.join("")}return t.length<6&&(t=t.replace(e.Color.re_hex3,"$1$1")),t!=="transparent"&&t.indexOf("#")<0&&(t="#"+t),t.toUpperCase()}}}(e)},"3.7.3",{requires:["dom-base"]}),YUI.add("dom-style-ie",function(e,t){(function(e){var t="hasLayout",n="px",r="filter",i="filters",s="opacity",o="auto",u="borderWidth",a="borderTopWidth",f="borderRightWidth",l="borderBottomWidth",c="borderLeftWidth",h="width",p="height",d="transparent",v="visible",m="getComputedStyle",g=undefined,y=e.config.doc.documentElement,b=e.Features.test,w=e.Features.add,E=/^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,S=e.UA.ie>=8,x=function(e){return e.currentStyle||e.style},T={CUSTOM_STYLES:{},get:function(t,r){var i="",o;return t&&(o=x(t)[r],r===s&&e.DOM.CUSTOM_STYLES[s]?i=e.DOM.CUSTOM_STYLES[s].get(t):!o||o.indexOf&&o.indexOf(n)>-1?i=o:e.DOM.IE.COMPUTED[r]?i=e.DOM.IE.COMPUTED[r](t,r):E.test(o)?i=T.getPixel(t,r)+n:i=o),i},sizeOffsets:{width:["Left","Right"],height:["Top","Bottom"],top:["Top"],bottom:["Bottom"]},getOffset:function(e,t){var r=x(e)[t],i=t.charAt(0).toUpperCase()+t.substr(1),s="offset"+i,u="pixel"+i,a=T.sizeOffsets[t],f=e.ownerDocument.compatMode,l="";return r===o||r.indexOf("%")>-1?(l=e["offset"+i],f!=="BackCompat"&&(a[0]&&(l-=T.getPixel(e,"padding"+a[0]),l-=T.getBorderWidth(e,"border"+a[0]+"Width",1)),a[1]&&(l-=T.getPixel(e,"padding"+a[1]),l-=T.getBorderWidth(e,"border"+a[1]+"Width",1)))):(!e.style[u]&&!e.style[t]&&(e.style[t]=r),l=e.style[u]),l+n},borderMap:{thin:S?"1px":"2px",medium:S?"3px":"4px",thick:S?"5px":"6px"},getBorderWidth:function(e,t,r){var i=r?"":n,s=e.currentStyle[t];return s.indexOf(n)<0&&(T.borderMap[s]&&e.currentStyle.borderStyle!=="none"?s=T.borderMap[s]:s=0),r?parseFloat(s):s},getPixel:function(e,t){var n=null,r=x(e),i=r.right,s=r[t];return e.style.right=s,n=e.style.pixelRight,e.style.right=i,n},getMargin:function(e,t){var r,i=x(e);return i[t]==o?r=0:r=T.getPixel(e,t),r+n},getVisibility:function(e,t){var n;while((n=e.currentStyle)&&n[t]=="inherit")e=e.parentNode;return n?n[t]:v},getColor:function(t,n){var r=x(t)[n];return(!r||r===d)&&e.DOM.elementByAxis(t,"parentNode",null,function(e){r=x(e)[n];if(r&&r!==d)return t=e,!0}),e.Color.toRGB(r)},getBorderColor:function(t,n){var r=x(t),i=r[n]||r.color;return e.Color.toRGB(e.Color.toHex(i))}},N={};w("style","computedStyle",{test:function(){return"getComputedStyle"in e.config.win}}),w("style","opacity",{test:function(){return"opacity"in y.style}}),w("style","filter",{test:function(){return"filters"in y}}),!b("style","opacity")&&b("style","filter")&&(e.DOM.CUSTOM_STYLES[s]={get:function(e){var t=100;try{t=e[i]["DXImageTransform.Microsoft.Alpha"][s]}catch(n){try{t=e[i]("alpha")[s]}catch(r){}}return t/100},set:function(e,n,i){var o,u=x(e),a=u[r];i=i||e.style,n===""&&(o=s in u?u[s]:1,n=o),typeof a=="string"&&(i[r]=a.replace(/alpha([^)]*\))/gi,"")+(n<1?"alpha("+s+"="+n*100+")":""),i[r]||i.removeAttribute(r),u[t]||(i.zoom=1))}});try{e.config.doc.createElement("div").style.height="-1px"}catch(C){e.DOM.CUSTOM_STYLES.height={set:function(e,t,n){var r=parseFloat(t);if(r>=0||t==="auto"||t==="")n.height=t}},e.DOM.CUSTOM_STYLES.width={set:function(e,t,n){var r=parseFloat(t);if(r>=0||t==="auto"||t==="")n.width=t}}}b("style","computedStyle")||(N[h]=N[p]=T.getOffset,N.color=N.backgroundColor=T.getColor,N[u]=N[a]=N[f]=N[l]=N[c]=T.getBorderWidth,N.marginTop=N.marginRight=N.marginBottom=N.marginLeft=T.getMargin,N.visibility=T.getVisibility,N.borderColor=N.borderTopColor=N.borderRightColor=N.borderBottomColor=N.borderLeftColor=T.getBorderColor,e.DOM[m]=T.get,e.namespace("DOM.IE"),e.DOM.IE.COMPUTED=N,e.DOM.IE.ComputedStyle=T)})(e)},"3.7.3",{requires:["dom-style"]}),YUI.add("dom-screen",function(e,t){(function(e){var t="documentElement",n="compatMode",r="position",i="fixed",s="relative",o="left",u="top",a="BackCompat",f="medium",l="borderLeftWidth",c="borderTopWidth",h="getBoundingClientRect",p="getComputedStyle",d=e.DOM,v=/^t(?:able|d|h)$/i,m;e.UA.ie&&(e.config.doc[n]!=="BackCompat"?m=t:m="body"),e.mix(d,{winHeight:function(e){var t=d._getWinSize(e).height;return t},winWidth:function(e){var t=d._getWinSize(e).width;return t},docHeight:function(e){var t=d._getDocSize(e).height;return Math.max(t,d._getWinSize(e).height)},docWidth:function(e){var t=d._getDocSize(e).width;return Math.max(t,d._getWinSize(e).width)},docScrollX:function(n,r){r=r||n?d._getDoc(n):e.config.doc;var i=r.defaultView,s=i?i.pageXOffset:0;return Math.max(r[t].scrollLeft,r.body.scrollLeft,s)},docScrollY:function(n,r){r=r||n?d._getDoc(n):e.config.doc;var i=r.defaultView,s=i?i.pageYOffset:0;return Math.max(r[t].scrollTop,r.body.scrollTop,s)},getXY:function(){return e.config.doc[t][h]?function(r){var i=null,s,o,u,f,l,c,p,v,g,y;if(r&&r.tagName){p=r.ownerDocument,u=p[n],u!==a?y=p[t]:y=p.body,y.contains?g=y.contains(r):g=e.DOM.contains(y,r);if(g){v=p.defaultView,v&&"pageXOffset"in v?(s=v.pageXOffset,o=v.pageYOffset):(s=m?p[m].scrollLeft:d.docScrollX(r,p),o=m?p[m].scrollTop:d.docScrollY(r,p)),e.UA.ie&&(!p.documentMode||p.documentMode<8||u===a)&&(l=y.clientLeft,c=y.clientTop),f=r[h](),i=[f.left,f.top];if(l||c)i[0]-=l,i[1]-=c;if(o||s)if(!e.UA.ios||e.UA.ios>=4.2)i[0]+=s,i[1]+=o}else i=d._getOffset(r)}return i}:function(t){var n=null,s,o,u,a,f;if(t)if(d.inDoc(t)){n=[t.offsetLeft,t.offsetTop],s=t.ownerDocument,o=t,u=e.UA.gecko||e.UA.webkit>519?!0:!1;while(o=o.offsetParent)n[0]+=o.offsetLeft,n[1]+=o.offsetTop,u&&(n=d._calcBorders(o,n));if(d.getStyle(t,r)!=i){o=t;while(o=o.parentNode){a=o.scrollTop,f=o.scrollLeft,e.UA.gecko&&d.getStyle(o,"overflow")!=="visible"&&(n=d._calcBorders(o,n));if(a||f)n[0]-=f,n[1]-=a}n[0]+=d.docScrollX(t,s),n[1]+=d.docScrollY(t,s)}else n[0]+=d.docScrollX(t,s),n[1]+=d.docScrollY(t,s)}else n=d._getOffset(t);return n}}(),getScrollbarWidth:e.cached(function(){var t=e.config.doc,n=t.createElement("div"),r=t.getElementsByTagName("body")[0],i=.1;return r&&(n.style.cssText="position:absolute;visibility:hidden;overflow:scroll;width:20px;",n.appendChild(t.createElement("p")).style.height="1px",r.insertBefore(n,r.firstChild),i=n.offsetWidth-n.clientWidth,r.removeChild(n)),i},null,.1),getX:function(e){return d.getXY(e)[0]},getY:function(e){return d.getXY(e)[1]},setXY:function(e,t,n){var i=d.setStyle,a,f,l,c;e&&t&&(a=d.getStyle(e,r),f=d._getOffset(e),a=="static"&&(a=s,i(e,r,a)),c=d.getXY(e),t[0]!==null&&i(e,o,t[0]-c[0]+f[0]+"px"),t[1]!==null&&i(e,u,t[1]-c[1]+f[1]+"px"),n||(l=d.getXY(e),(l[0]!==t[0]||l[1]!==t[1])&&d.setXY(e,t,!0)))},setX:function(e,t){return d.setXY(e,[t,null])},setY:function(e,t){return d.setXY(e,[null,t])},swapXY:function(e,t){var n=d.getXY(e);d.setXY(e,d.getXY(t)),d.setXY(t,n)},_calcBorders:function(t,n){var r=parseInt(d[p](t,c),10)||0,i=parseInt(d[p](t,l),10)||0;return e.UA.gecko&&v.test(t.tagName)&&(r=0,i=0),n[0]+=i,n[1]+=r,n},_getWinSize:function(r,i){i=i||r?d._getDoc(r):e.config.doc;var s=i.defaultView||i.parentWindow,o=i[n],u=s.innerHeight,a=s.innerWidth,f=i[t];return o&&!e.UA.opera&&(o!="CSS1Compat"&&(f=i.body),u=f.clientHeight,a=f.clientWidth),{height:u,width:a}},_getDocSize:function(r){var i=r?d._getDoc(r):e.config.doc,s=i[t];return i[n]!="CSS1Compat"&&(s=i.body),{height:s.scrollHeight,width:s.scrollWidth}}})})(e),function(e){var t="top",n="right",r="bottom",i="left",s=function(e,s){var o=Math.max(e[t],s[t]),u=Math.min(e[n],s[n]),a=Math.min(e[r],s[r]),f=Math.max(e[i],s[i]),l={};return l[t]=o,l[n]=u,l[r]=a,l[i]=f,l},o=e.DOM;e.mix(o,{region:function(e){var t=o.getXY(e),n=!1;return e&&t&&(n=o._getRegion(t[1],t[0]+e.offsetWidth,t[1]+e.offsetHeight,t[0])),n},intersect:function(u,a,f){var l=f||o.region(u),c={},h=a,p;if(h.tagName)c=o.region(h);else{if(!e.Lang.isObject(a))return!1;c=a}return p=s(c,l),{top:p[t],right:p[n],bottom:p[r],left:p[i],area:(p[r]-p[t])*(p[n]-p[i]),yoff:p[r]-p[t],xoff:p[n]-p[i],inRegion:o.inRegion(u,a,!1,f)}},inRegion:function(u,a,f,l){var c={},h=l||o.region(u),p=a,d;if(p.tagName)c=o.region(p);else{if(!e.Lang.isObject(a))return!1;c=a}return f?h[i]>=c[i]&&h[n]<=c[n]&&h[t]>=c[t]&&h[r]<=c[r]:(d=s(c,h),d[r]>=d[t]&&d[n]>=d[i]?!0:!1)},inViewportRegion:function(e,t,n){return o.inRegion(e,o.viewportRegion(e),t,n)},_getRegion:function(e,s,o,u){var a={};return a[t]=a[1]=e,a[i]=a[0]=u,a[r]=o,a[n]=s,a.width=a[n]-a[i],a.height=a[r]-a[t],a},viewportRegion:function(t){t=t||e.config.doc.documentElement;var n=!1,r,i;return t&&(r=o.docScrollX(t),i=o.docScrollY(t),n=o._getRegion(i,o.winWidth(t)+r,i+o.winHeight(t),r)),n}})}(e)},"3.7.3",{requires:["dom-base","dom-style"]}),YUI.add("selector-native",function(e,t){(function(e){e.namespace("Selector");var t="compareDocumentPosition",n="ownerDocument",r={_types:{esc:{token:"\ue000",re:/\\[:\[\]\(\)#\.\'\>+~"]/gi},attr:{token:"\ue001",re:/(\[[^\]]*\])/g},pseudo:{token:"\ue002",re:/(\([^\)]*\))/g}},useNative:!0,_escapeId:function(e){return e&&(e=e.replace(/([:\[\]\(\)#\.'<>+~"])/g,"\\$1")),e},_compare:"sourceIndex"in e.config.doc.documentElement?function(e,t){var n=e.sourceIndex,r=t.sourceIndex;return n===r?0:n>r?1:-1}:e.config.doc.documentElement[t]?function(e,n){return e[t](n)&4?-1:1}:function(e,t){var r,i,s;return e&&t&&(r=e[n].createRange(),r.setStart(e,0),i=t[n].createRange(),i.setStart(t,0),s=r.compareBoundaryPoints(1,i)),s},_sort:function(t){return t&&(t=e.Array(t,0,!0),t.sort&&t.sort(r._compare)),t},_deDupe:function(e){var t=[],n,r;for(n=0;r=e[n++];)r._found||(t[t.length]=r,r._found=!0);for(n=0;r=t[n++];)r._found=null,r.removeAttribute("_found");return t},query:function(t,n,i,s){n=n||e.config.doc;var o=[],u=e.Selector.useNative&&e.config.doc.querySelector&&!s,a=[[t,n]],f,l,c,h=u?e.Selector._nativeQuery:e.Selector._bruteQuery;if(t&&h){!s&&(!u||n.tagName)&&(a=r._splitQueries(t,n));for(c=0;f=a[c++];)l=h(f[0],f[1],i),i||(l=e.Array(l,0,!0)),l&&(o=o.concat(l));a.length>1&&(o=r._sort(r._deDupe(o)))}return i?o[0]||null:o},_replaceSelector:function(t){var n=e.Selector._parse("esc",t),i,s;return t=e.Selector._replace("esc",t),s=e.Selector._parse("pseudo",t),t=r._replace("pseudo",t),i=e.Selector._parse("attr",t),t=e.Selector._replace("attr",t),{esc:n,attrs:i,pseudos:s,selector:t}},_restoreSelector:function(t){var n=t.selector;return n=e.Selector._restore("attr",n,t.attrs),n=e.Selector._restore("pseudo",n,t.pseudos),n=e.Selector._restore("esc",n,t.esc),n},_replaceCommas:function(t){var n=e.Selector._replaceSelector(t),t=n.selector;return t&&(t=t.replace(/,/g,"\ue007"),n.selector=t,t=e.Selector._restoreSelector(n)),t},_splitQueries:function(t,n){t.indexOf(",")>-1&&(t=e.Selector._replaceCommas(t));var r=t.split("\ue007"),i=[],s="",o,u,a;if(n){n.nodeType===1&&(o=e.Selector._escapeId(e.DOM.getId(n)),o||(o=e.guid(),e.DOM.setId(n,o)),s='[id="'+o+'"] ');for(u=0,a=r.length;u<a;++u)t=s+r[u],i.push([t,n])}return i},_nativeQuery:function(t,n,r){if(e.UA.webkit&&t.indexOf(":checked")>-1&&e.Selector.pseudos&&e.Selector.pseudos.checked)return e.Selector.query(t,n,r,!0);try{return n["querySelector"+(r?"":"All")](t)}catch(i){return e.Selector.query(t,n,r,!0)}},filter:function(t,n){var r=[],i,s;if(t&&n)for(i=0;s=t[i++];)e.Selector.test(s,n)&&(r[r.length]=s);return r},test:function(t,r,i){var s=!1,o=!1,u,a,f,l,c,h,p,d,v;if(t&&t.tagName)if(typeof r=="function")s=r.call(t,t);else{u=r.split(","),!i&&!e.DOM.inDoc(t)&&(a=t.parentNode,a?i=a:(c=t[n].createDocumentFragment(),c.appendChild(t),i=c,o=!0)),i=i||t[n],h=e.Selector._escapeId(e.DOM.getId(t)),h||(h=e.guid(),e.DOM.setId(t,h));for(p=0;v=u[p++];){v+='[id="'+h+'"]',l=e.Selector.query(v,i);for(d=0;f=l[d++];)if(f===t){s=!0;break}if(s)break}o&&c.removeChild(t)}return s},ancestor:function(t,n,r){return e.DOM.ancestor(t,function(t){return e.Selector.test(t,n)},r)},_parse:function(t,n){return n.match(e.Selector._types[t].re)},_replace:function(t,n){var r=e.Selector._types[t];return n.replace(r.re,r.token)},_restore:function(t,n,r){if(r){var i=e.Selector._types[t].token,s,o;for(s=0,o=r.length;s<o;++s)n=n.replace(i,r[s])}return n}};e.mix(e.Selector,r,!0)})(e)},"3.7.3",{requires:["dom-base"]}),YUI.add("selector",function(e,t){},"3.7.3",{requires:["selector-native"]}),YUI.add("event-custom-base",function(e,t){e.Env.evt={handles:{},plugins:{}};var n=0,r=1,i={objs:null,before:function(t,r,i,s){var o=t,u;return s&&(u=[t,s].concat(e.Array(arguments,4,!0)),o=e.rbind.apply(e,u)),this._inject(n,o,r,i)},after:function(t,n,i,s){var o=t,u;return s&&(u=[t,s].concat(e.Array(arguments,4,!0)),o=e.rbind.apply(e,u)),this._inject(r,o,n,i)},_inject:function(t,n,r,i){var s=e.stamp(r),o,u;return r._yuiaop||(r._yuiaop={}),o=r._yuiaop,o[i]||(o[i]=new e.Do.Method(r,i),r[i]=function(){return o[i].exec.apply(o[i],arguments)}),u=s+e.stamp(n)+i,o[i].register(u,n,t),new e.EventHandle(o[i],u)},detach:function(e){e.detach&&e.detach()},_unload:function(e,t){}};e.Do=i,i.Method=function(e,t){this.obj=e,this.methodName=t,this.method=e[t],this.before={},this.after={}},i.Method.prototype.register=function(e,t,n){n?this.after[e]=t:this.before[e]=t},i.Method.prototype._delete=function(e){delete this.before[e],delete this.after[e]},i.Method.prototype.exec=function(){var t=e.Array(arguments,0,!0),n,r,s,o=this.before,u=this.after,a=!1;for(n in o)if(o.hasOwnProperty(n)){r=o[n].apply(this.obj,t);if(r)switch(r.constructor){case i.Halt:return r.retVal;case i.AlterArgs:t=r.newArgs;break;case i.Prevent:a=!0;break;default:}}a||(r=this.method.apply(this.obj,t)),i.originalRetVal=r,i.currentRetVal=r;for(n in u)if(u.hasOwnProperty(n)){s=u[n].apply(this.obj,t);if(s&&s.constructor==i.Halt)return s.retVal;s&&s.constructor==i.AlterReturn&&(r=s.newRetVal,i.currentRetVal=r)}return r},i.AlterArgs=function(e,t){this.msg=e,this.newArgs=t},i.AlterReturn=function(e,t){this.msg=e,this.newRetVal=t},i.Halt=function(e,t){this.msg=e,this.retVal=t},i.Prevent=function(e){this.msg=e},i.Error=i.Halt;var s=e.Array,o="after",u=["broadcast","monitored","bubbles","context","contextFn","currentTarget","defaultFn","defaultTargetOnly","details","emitFacade","fireOnce","async","host","preventable","preventedFn","queuable","silent","stoppedFn","target","type"],a=s.hash(u),f=Array.prototype.slice,l=9,c="yui:log",h=function(e,t,n){var r;for(r in t)a[r]&&(n||!(r in e))&&(e[r]=t[r]);return e};e.CustomEvent=function(t,n){this._kds=e.CustomEvent.keepDeprecatedSubs,n=n||{},this.id=e.stamp(this),this.type=t,this.context=e,this.logSystem=t==c,this.silent=this.logSystem,this._kds&&(this.subscribers={}),this._subscribers=[],this._kds&&(this.afters={}),this._afters=[],this.preventable=!0,this.bubbles=!0,this.signature=l,this.applyConfig(n,!0)},e.CustomEvent.keepDeprecatedSubs=!1,e.CustomEvent.mixConfigs=h,e.CustomEvent.prototype={constructor:e.CustomEvent,hasSubs:function(e){var t=this._subscribers.length,n=this._afters.length,r=this.sibling;return r&&(t+=r._subscribers.length,n+=r._afters.length),e?e=="after"?n:t:t+n},monitor:function(e){this.monitored=!0;var t=this.id+"|"+this.type+"_"+e,n=f.call(arguments,0);return n[0]=t,this.host.on.apply(this.host,n)},getSubs:function(){var e=this._subscribers,t=this._afters,n=this.sibling;return e=n?e.concat(n._subscribers):e.concat(),t=n?t.concat(n._afters):t.concat(),[e,t]},applyConfig:function(e,t){h(this,e,t)},_on:function(t,n,r,i){t||this.log("Invalid callback for CE: "+this.type);var s=new e.Subscriber(t,n,r,i);return this.fireOnce&&this.fired&&(this.async?setTimeout(e.bind(this._notify,this,s,this.firedWith),0):this._notify(s,this.firedWith)),i==o?this._afters.push(s):this._subscribers.push(s),this._kds&&(i==o?this.afters[s.id]=s:this.subscribers[s.id]=s),new e.EventHandle(this,s)},subscribe:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this._on(e,t,n,!0)},on:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this.monitored&&this.host&&this.host._monitor("attach",this,{args:arguments}),this._on(e,t,n,!0)},after:function(e,t){var n=arguments.length>2?f.call(arguments,2):null;return this._on(e,t,n,o)},detach:function(e,t){if(e&&e.detach)return e.detach();var n,r,i=0,s=this._subscribers,o=this._afters;for(n=s.length;n>=0;n--)r=s[n],r&&(!e||e===r.fn)&&(this._delete(r,s,n),i++);for(n=o.length;n>=0;n--)r=o[n],r&&(!e||e===r.fn)&&(this._delete(r,o,n),i++);return i},unsubscribe:function(){return this.detach.apply(this,arguments)},_notify:function(e,t,n){this.log(this.type+"->"+"sub: "+e.id);var r;return r=e.notify(t,this),!1===r||this.stopped>1?(this.log(this.type+" cancelled by subscriber"),!1):!0},log:function(e,t){},fire:function(){if(this.fireOnce&&this.fired)return this.log("fireOnce event: "+this.type+" already fired"),!0;var e=f.call(arguments,0);return this.fired=!0,this.fireOnce&&(this.firedWith=e),this.emitFacade?this.fireComplex(e):this.fireSimple(e)},fireSimple:function(e){this.stopped=0,this.prevented=0;if(this.hasSubs()){var t=this.getSubs();this._procSubs(t[0],e),this._procSubs(t[1],e)}return this._broadcast(e),this.stopped?!1:!0},fireComplex:function(e){return this.log("Missing event-custom-complex needed to emit a facade for: "+this.type),e[0]=e[0]||{},this.fireSimple(e)},_procSubs:function(e,t,n){var r,i,s;for(i=0,s=e.length;i<s;i++){r=e[i];if(r&&r.fn){!1===this._notify(r,t,n)&&(this.stopped=2);if(this.stopped==2)return!1}}return!0},_broadcast:function(t){if(!this.stopped&&this.broadcast){var n=t.concat();n.unshift(this.type),this.host!==e&&e.fire.apply(e,n),this.broadcast==2&&e.Global.fire.apply(e.Global,n)}},unsubscribeAll:function(){return this.detachAll.apply(this,arguments)},detachAll:function(){return this.detach()},_delete:function(e,t,n){var r=e._when;t||(t=r===o?this._afters:this._subscribers,n=s.indexOf(t,e,0)),e&&t[n]===e&&t.splice(n,1),this._kds&&(r===o?delete this.afters[e.id]:delete this.subscribers[e.id]),this.monitored&&this.host&&this.host._monitor("detach",this,{ce:this,sub:e}),e&&(e.deleted=!0)}},e.Subscriber=function(t,n,r,i){this.fn=t,this.context=n,this.id=e.stamp(this),this.args=r,this._when=i},e.Subscriber.prototype={constructor:e.Subscriber,_notify:function(e,t,n){if(this.deleted&&!this.postponed){if(!this.postponed)return delete this.postponed,null;delete this.fn,delete this.context}var r=this.args,i;switch(n.signature){case 0:i=this.fn.call(e,n.type,t,e);break;case 1:i=this.fn.call(e,t[0]||null,e);break;default:r||t?(t=t||[],r=r?t.concat(r):t,i=this.fn.apply(e,r)):i=this.fn.call(e)}return this.once&&n._delete(this),i},notify:function(t,n){var r=this.context,i=!0;r||(r=n.contextFn?n.contextFn():n.context);if(e.config&&e.config.throwFail)i=this._notify(r,t,n);else try{i=this._notify(r,t,n)}catch(s){e.error(this+" failed: "+s.message,s)}return i},contains:function(e,t){return t?this.fn==e&&this.context==t:this.fn==e},valueOf:function(){return this.id}},e.EventHandle=function(e,t){this.evt=e,this.sub=t},e.EventHandle.prototype={batch:function(t,n){t.call(n||this,this),e.Lang.isArray(this.evt)&&e.Array.each(this.evt,function(e){e.batch.call(n||e,t)})},detach:function(){var t=this.evt,n=0,r;if(t)if(e.Lang.isArray(t))for(r=0;r<t.length;r++)n+=t[r].detach();else t._delete(this.sub),n=1;return n},monitor:function(e){return this.evt.monitor.apply(this.evt,arguments)}};var p=e.Lang,d=":",v="|",m="~AFTER~",g=/(.*?)(:)(.*?)/,y=e.cached(function(e){return e.replace(g,"*$2$3")}),b=e.cached(function(e,t){return!t||typeof e!="string"||e.indexOf(d)>-1?e:t+d+e}),w=e.cached(function(e,t){var n=e,r,i,s;return p.isString(n)?(s=n.indexOf(m),s>-1&&(i=!0,n=n.substr(m.length)),s=n.indexOf(v),s>-1&&(r=n.substr(0,s),n=n.substr(s+1),n=="*"&&(n=null)),[r,t?b(n,t):n,i,n]):n}),E=function(t){var n=p.isObject(t)?t:{};this._yuievt=this._yuievt||{id:e.guid(),events:{},targets:{},config:n,chain:"chain"in n?n.chain:e.config.chain,bubbling:!1,defaults:{context:n.context||this,host:this,emitFacade:n.emitFacade,fireOnce:n.fireOnce,queuable:n.queuable,monitored:n.monitored,broadcast:n.broadcast,defaultTargetOnly:n.defaultTargetOnly,bubbles:"bubbles"in n?n.bubbles:!0}}};E.prototype={constructor:E,once:function(){var e=this.on.apply(this,arguments);return e.batch(function(e){e.sub&&(e.sub.once=!0)}),e},onceAfter:function(){var e=this.after.apply(this,arguments);return e.batch(function(e){e.sub&&(e.sub.once=!0)}),e},parseType:function(e,t){return w(e,t||this._yuievt.config.prefix)},on:function(t,n,r){var i=this._yuievt,s=w(t,i.config.prefix),o,u,a,l,c,h,d,v=e.Env.evt.handles,g,y,b,E=e.Node,S,x,T;this._monitor("attach",s[1],{args:arguments,category:s[0],after:s[2]});if(p.isObject(t))return p.isFunction(t)?e.Do.before.apply(e.Do,arguments):(o=n,u=r,a=f.call(arguments,0),l=[],p.isArray(t)&&(T=!0),g=t._after,delete t._after,e.each(t,function(e,t){p.isObject(e)&&(o=e.fn||(p.isFunction(e)?e:o),u=e.context||u);var n=g?m:"";a[0]=n+(T?e:t),a[1]=o,a[2]=u,l.push(this.on.apply(this,a))},this),i.chain?this:new e.EventHandle(l));h=s[0],g=s[2],b=s[3];if(E&&e.instanceOf(this,E)&&b in E.DOM_EVENTS)return a=f.call(arguments,0),a.splice(2,0,E.getDOMNode(this)),e.on.apply(e,a);t=s[1];if(e.instanceOf(this,YUI)){y=e.Env.evt.plugins[t],a=f.call(arguments,0),a[0]=b,E&&(S=a[2],e.instanceOf(S,e.NodeList)?S=e.NodeList.getDOMNodes(S):e.instanceOf(S,E)&&(S=E.getDOMNode(S)),x=b in E.DOM_EVENTS,x&&(a[2]=S));if(y)d=y.on.apply(e,a);else if(!t||x)d=e.Event._attach(a)}return d||(c=i.events[t]||this.publish(t),d=c._on(n,r,arguments.length>3?f.call(arguments,3):null,g?"after":!0)),h&&(v[h]=v[h]||{},v[h][t]=v[h][t]||[],v[h][t].push(d)),i.chain?this:d},subscribe:function(){return this.on.apply(this,arguments)},detach:function(t,n,r){var i=this._yuievt.events,s,o=e.Node,u=o&&e.instanceOf(this,o);if(!t&&this!==e){for(s in i)i.hasOwnProperty(s)&&i[s].detach(n,r);return u&&e.Event.purgeElement(o.getDOMNode(this)),this}var a=w(t,this._yuievt.config.prefix),l=p.isArray(a)?a[0]:null,c=a?a[3]:null,h,d=e.Env.evt.handles,v,m,g,y,b=function(e,t,n){var r=e[t],i,s;if(r)for(s=r.length-1;s>=0;--s)i=r[s].evt,(i.host===n||i.el===n)&&r[s].detach()};if(l){m=d[l],t=a[1],v=u?e.Node.getDOMNode(this):this;if(m){if(t)b(m,t,v);else for(s in m)m.hasOwnProperty(s)&&b(m,s,v);return this}}else{if(p.isObject(t)&&t.detach)return t.detach(),this;if(u&&(!c||c in o.DOM_EVENTS))return g=f.call(arguments,0),g[2]=o.getDOMNode(this),e.detach.apply(e,g),this}h=e.Env.evt.plugins[c];if(e.instanceOf(this,YUI)){g=f.call(arguments,0);if(h&&h.detach)return h.detach.apply(e,g),this;if(!t||!h&&o&&t in o.DOM_EVENTS)return g[0]=t,e.Event.detach.apply(e.Event,g),this}return y=i[a[1]],y&&y.detach(n,r),this},unsubscribe:function(){return this.detach.apply(this,arguments)},detachAll:function(e){return this.detach(e)},unsubscribeAll:function(){return this.detachAll.apply(this,arguments)},publish:function(t,n){var r,i,s,o,u=this._yuievt,a=u.config.prefix;return p.isObject(t)?(s={},e.each(t,function(e,t){s[t]=this.publish(t,e||n)},this),s):(t=a?b(t,a):t,r=u.events,i=r[t],this._monitor("publish",t,{args:arguments}),i?n&&i.applyConfig(n,!0):(o=u.defaults,i=new e.CustomEvent(t,o),n&&i.applyConfig(n,!0),r[t]=i),r[t])},_monitor:function(e,t,n){var r,i,s;if(t){typeof t=="string"?(s=t,i=this.getEvent(t,!0)):(i=t,s=t.type);if(this._yuievt.config.monitored&&(!i||i.monitored)||i&&i.monitored)r=s+"_"+e,n.monitored=e,this.fire.call(this,r,n)}},fire:function(e){var t=p.isString(e),n=t?e:e&&e.type,r=this._yuievt,i=r.config.prefix,s,o,u,a=t?f.call(arguments,1):arguments;n=i?b(n,i):n,s=this.getEvent(n,!0),u=this.getSibling(n,s),u&&!s&&(s=this.publish(n)),this._monitor("fire",s||n,{args:a});if(!s){if(r.hasTargets)return this.bubble({type:n},a,this);o=!0}else s.sibling=u,o=s.fire.apply(s,a);return r.chain?this:o},getSibling:function(e,t){var n;return e.indexOf(d)>-1&&(e=y(e),n=this.getEvent(e,!0),n&&(n.applyConfig(t),n.bubbles=!1,n.broadcast=0)),n},getEvent:function(e,t){var n,r;return t||(n=this._yuievt.config.prefix,e=n?b(e,n):e),r=this._yuievt.events,r[e]||null},after:function(t,n){var r=f.call(arguments,0);switch(p.type(t)){case"function":return e.Do.after.apply(e.Do,arguments);case"array":case"object":r[0]._after=!0;break;default:r[0]=m+t}return this.on.apply(this,r)},before:function(){return this.on.apply(this,arguments)}},e.EventTarget=E,e.mix(e,E.prototype),E.call(e,{bubbles:!1}),YUI.Env.globalEvents=YUI.Env.globalEvents||new E,e.Global=YUI.Env.globalEvents},"3.7.3",{requires:["oop"]}),YUI.add("event-custom-complex",function(e,t){var n,r,i,s={},o=e.CustomEvent.prototype,u=e.EventTarget.prototype,a=function(e,t){var n;for(n in t)r.hasOwnProperty(n)||(e[n]=t[n])};e.EventFacade=function(e,t){e=e||s,this._event=e,this.details=e.details,this.type=e.type,this._type=e.type,this.target=e.target,this.currentTarget=t,this.relatedTarget=e.relatedTarget},e.mix(e.EventFacade.prototype,{stopPropagation:function(){this._event.stopPropagation(),this.stopped=1},stopImmediatePropagation:function(){this._event.stopImmediatePropagation(),this.stopped=2},preventDefault:function(){this._event.preventDefault(),this.prevented=1},halt:function(e){this._event.halt(e),this.prevented=1,this.stopped=e?2:1}}),o.fireComplex=function(t){var n,r,i,s,o,u,a,f,l,c=this,h=c.host||c,p,d;if(c.stack&&c.queuable&&c.type!=c.stack.next.type)return c.log("queue "+c.type),c.stack.queue.push([c,t]),!0;n=c.stack||{id:c.id,next:c,silent:c.silent,stopped:0,prevented:0,bubbling:null,type:c.type,afterQueue:new e.Queue,defaultTargetOnly:c.defaultTargetOnly,queue:[]},f=c.getSubs(),c.stopped=c.type!==n.type?0:n.stopped,c.prevented=c.type!==n.type?0:n.prevented,c.target=c.target||h,c.stoppedFn&&(a=new e.EventTarget({fireOnce:!0,context:h}),c.events=a,a.on("stopped",c.stoppedFn)),c.currentTarget=h,c.details=t.slice(),c.log("Firing "+c.type),c._facade=null,r=c._getFacade(t),e.Lang.isObject(t[0])?t[0]=r:t.unshift(r),f[0]&&c._procSubs(f[0],t,r),c.bubbles&&h.bubble&&!c.stopped&&(d=n.bubbling,n.bubbling=c.type,n.type!=c.type&&(n.stopped=0,n.prevented=0),u=h.bubble(c,t,null,n),c.stopped=Math.max(c.stopped,n.stopped),c.prevented=Math.max(c.prevented,n.prevented),n.bubbling=d),c.prevented?c.preventedFn&&c.preventedFn.apply(h,t):c.defaultFn&&(!c.defaultTargetOnly&&!n.defaultTargetOnly||h===r.target)&&c.defaultFn.apply(h,t),c._broadcast(t);if(f[1]&&!c.prevented&&c.stopped<2)if(n.id===c.id||c.type!=h._yuievt.bubbling){c._procSubs(f[1],t,r);while(p=n.afterQueue.last())p()}else l=f[1],n.execDefaultCnt&&(l=e.merge(l),e.each(l,function(e){e.postponed=!0})),n.afterQueue.add(function(){c._procSubs(l,t,r)});c.target=null;if(n.id===c.id){s=n.queue;while(s.length)i=s.pop(),o=i[0],n.next=o,o.fire.apply(o,i[1]);c.stack=null}return u=!c.stopped,c.type!=h._yuievt.bubbling&&(n.stopped=0,n.prevented=0,c.stopped=0,c.prevented=0),c._facade=null,u},o._getFacade=function(){var t=this._facade,n,r=this.details;return t||(t=new e.EventFacade(this,this.currentTarget)),n=r&&r[0],e.Lang.isObject(n,!0)&&(a(t,n),t.type=n.type||t.type),t.details=this.details,t.target=this.originalTarget||this.target,t.currentTarget=this.currentTarget,t.stopped=0,t.prevented=0,this._facade=t,this._facade},o.stopPropagation=function(){this.stopped=1,this.stack&&(this.stack.stopped=1),this.events&&this.events.fire("stopped",this)},o.stopImmediatePropagation=function(){this.stopped=2,this.stack&&(this.stack.stopped=2),this.events&&this.events.fire("stopped",this)},o.preventDefault=function(){this.preventable&&(this.prevented=1,this.stack&&(this.stack.prevented=1))},o.halt=function(e){e?this.stopImmediatePropagation():this.stopPropagation(),this.preventDefault()},u.addTarget=function(t){this._yuievt.targets[e.stamp(t)]=t,this._yuievt.hasTargets=!0},u.getTargets=function(){return e.Object.values(this._yuievt.targets)},u.removeTarget=function(t){delete this._yuievt.targets[e.stamp(t)]},u.bubble=function(e,t,n,r){var i=this._yuievt.targets,s=!0,o,u=e&&e.type,a,f,l,c,h=n||e&&e.target||this,p;if(!e||!e.stopped&&i)for(f in i)if(i.hasOwnProperty(f)){o=i[f],a=o.getEvent(u,!0),c=o.getSibling(u,a),c&&!a&&(a=o.publish(u)),p=o._yuievt.bubbling,o._yuievt.bubbling=u;if(!a)o._yuievt.hasTargets&&o.bubble(e,t,h,r);else{a.sibling=c,a.target=h,a.originalTarget=h,a.currentTarget=o,l=a.broadcast,a.broadcast=!1,a.emitFacade=!0,a.stack=r,s=s&&a.fire.apply(a,t||e.details||[]),a.broadcast=l,a.originalTarget=null;if(a.stopped)break}o._yuievt.bubbling=p}return s},n=new e.EventFacade,r={};for(i in n)r[i]=!0},"3.7.3",{requires:["event-custom-base"]}),YUI.add("node-core",function(e,t){var n=".",r="nodeName",i="nodeType",s="ownerDocument",o="tagName",u="_yuid",a={},f=Array.prototype.slice,l=e.DOM,c=function(t){if(!this.getDOMNode)return new c(t);if(typeof t=="string"){t=c._fromString(t);if(!t)return null}var n=t.nodeType!==9?t.uniqueID:t[u];n&&c._instances[n]&&c._instances[n]._node!==t&&(t[u]=null),n=n||e.stamp(t),n||(n=e.guid()),this[u]=n,this._node=t,this._stateProxy=t,this._initPlugins&&this._initPlugins()},h=function(t){var n=null;return t&&(n=typeof t=="string"?function(n){return e.Selector.test(n,t)}:function(n){return t(e.one(n))}),n};c.ATTRS={},c.DOM_EVENTS={},c._fromString=function(t){return t&&(t.indexOf("doc")===0?t=e.config.doc:t.indexOf("win")===0?t=e.config.win:t=e.Selector.query(t,null,!0)),t||null},c.NAME="node",c.re_aria=/^(?:role$|aria-)/,c.SHOW_TRANSITION="fadeIn",c.HIDE_TRANSITION="fadeOut",c._instances={},c.getDOMNode=function(e){return e?e.nodeType?e:e._node||null:null},c.scrubVal=function(t,n){if(t){if(typeof t=="object"||typeof t=="function")if(i in t||l.isWindow(t))t=e.one(t);else if(t.item&&!t._nodes||t[0]&&t[0][i])t=e.all(t)}else typeof t=="undefined"?t=n:t===null&&(t=null);return t},c.addMethod=function(e,t,n){e&&t&&typeof t=="function"&&(c.prototype[e]=function(){var e=f.call(arguments),n=this,r;return e[0]&&e[0]._node&&(e[0]=e[0]._node),e[1]&&e[1]._node&&(e[1]=e[1]._node),e.unshift(n._node),r=t.apply(n,e),r&&(r=c.scrubVal(r,n)),typeof r!="undefined"||(r=n),r})},c.importMethod=function(t,n,r){typeof n=="string"?(r=r||n,c.addMethod(r,t[n],t)):e.Array.each(n,function(e){c.importMethod(t,e)})},c.one=function(t){var n=null,r,i;if(t){if(typeof t=="string"){t=c._fromString(t);if(!t)return null}else if(t.getDOMNode)return t;if(t.nodeType||e.DOM.isWindow(t)){i=t.uniqueID&&t.nodeType!==9?t.uniqueID:t._yuid,n=c._instances[i],r=n?n._node:null;if(!n||r&&t!==r)n=new c(t),t.nodeType!=11&&(c._instances[n[u]]=n)}}return n},c.DEFAULT_SETTER=function(t,r){var i=this._stateProxy,s;return t.indexOf(n)>-1?(s=t,t=t.split(n),e.Object.setValue(i,t,r)):typeof i[t]!="undefined"&&(i[t]=r),r},c.DEFAULT_GETTER=function(t){var r=this._stateProxy,i;return t.indexOf&&t.indexOf(n)>-1?i=e.Object.getValue(r,t.split(n)):typeof r[t]!="undefined"&&(i=r[t]),i},e.mix(c.prototype,{DATA_PREFIX:"data-",toString:function(){var e=this[u]+": not bound to a node",t=this._node,n,i,s;return t&&(n=t.attributes,i=n&&n.id?t.getAttribute("id"):null,s=n&&n.className?t.getAttribute("className"):null,e=t[r],i&&(e+="#"+i),s&&(e+="."+s.replace(" ",".")),e+=" "+this[u]),e},get:function(e){var t;return this._getAttr?t=this._getAttr(e):t=this._get(e),t?t=c.scrubVal(t,this):t===null&&(t=null),t},_get:function(e){var t=c.ATTRS[e],n;return t&&t.getter?n=t.getter.call(this):c.re_aria.test(e)?n=this._node.getAttribute(e,2):n=c.DEFAULT_GETTER.apply(this,arguments),n},set:function(e,t){var n=c.ATTRS[e];return this._setAttr?this._setAttr.apply(this,arguments):n&&n.setter?n.setter.call(this,t,e):c.re_aria.test(e)?this._node.setAttribute(e,t):c.DEFAULT_SETTER.apply(this,arguments),this},setAttrs:function(t){return this._setAttrs?this._setAttrs(t):e.Object.each(t,function(e,t){this.set(t,e)},this),this},getAttrs:function(t){var n={};return this._getAttrs?this._getAttrs(t):e.Array.each(t,function(e,t){n[e]=this.get(e)},this),n},compareTo:function(e){var t=this._node;return e&&e._node&&(e=e._node),t===e},inDoc:function(e){var t=this._node;e=e?e._node||e:t[s];if(e.documentElement)return l.contains(e.documentElement,t)},getById:function(t){var n=this._node,r=l.byId(t,n[s]);return r&&l.contains(n,r)?r=e.one(r):r=null,r},ancestor:function(t,n,r){return arguments.length===2&&(typeof n=="string"||typeof n=="function")&&(r=n),e.one(l.ancestor(this._node,h(t),n,h(r)))},ancestors:function(t,n,r){return arguments.length===2&&(typeof n=="string"||typeof n=="function")&&(r=n),e.all(l.ancestors(this._node,h(t),n,h(r)))},previous:function(t,n){return e.one(l.elementByAxis(this._node,"previousSibling",h(t),n))},next:function(t,n){return e.one(l.elementByAxis(this._node,"nextSibling",h(t),n))},siblings:function(t){return e.all(l.siblings(this._node,h(t)))},one:function(t){return e.one(e.Selector.query(t,this._node,!0))},all:function(t){var n=e.all(e.Selector.query(t,this._node));return n._query=t,n._queryRoot=this._node,n},test:function(t){return e.Selector.test(this._node,t)},remove:function(e){var t=this._node;return t&&t.parentNode&&t.parentNode.removeChild(t),e&&this.destroy(),this},replace:function(e){var t=this._node;return typeof e=="string"&&(e=c.create(e)),t.parentNode.replaceChild(c.getDOMNode(e),t),this},replaceChild:function(t,n){return typeof t=="string"&&(t=l.create(t)),e.one(this._node.replaceChild(c.getDOMNode(t),c.getDOMNode(n)))},destroy:function(t){var n=e.config.doc.uniqueID?"uniqueID":"_yuid",r;this.purge(),this.unplug&&this.unplug(),this.clearData(),t&&e.NodeList.each(this.all("*"),function(t){r=c._instances[t[n]],r?r.destroy():e.Event.purgeElement(t)}),this._node=null,this._stateProxy=null,delete c._instances[this._yuid]},invoke:function(e,t,n,r,i,s){var o=this._node,u;return t&&t._node&&(t=t._node),n&&n._node&&(n=n._node),u=o[e](t,n,r,i,s),c.scrubVal(u,this)},swap:e.config.doc.documentElement.swapNode?function(e){this._node.swapNode(c.getDOMNode(e))}:function(e){e=c.getDOMNode(e);var t=this._node,n=e.parentNode,r=e.nextSibling;return r===t?n.insertBefore(t,e):e===t.nextSibling?n.insertBefore(e,t):(t.parentNode.replaceChild(e,t),l.addHTML(n,t,r)),this},hasMethod:function(e){var t=this._node;return!(!(t&&e in t&&typeof t[e]!="unknown")||typeof t[e]!="function"&&String(t[e]).indexOf("function")!==1)},isFragment:function(){return this.get("nodeType")===11},empty:function(){return this.get("childNodes").remove().destroy(!0),this},getDOMNode:function(){return this._node}},!0),e.Node=c,e.one=c.one;var p=function(t){var n=[];t&&(typeof t=="string"?(this._query=t,t=e.Selector.query(t)):t.nodeType||l.isWindow(t)?t=[t]:t._node?t=[t._node]:t[0]&&t[0]._node?(e.Array.each(t,function(e){e._node&&n.push(e._node)}),t=n):t=e.Array(t,0,!0)),this._nodes=t||[]};p.NAME="NodeList",p.getDOMNodes=function(e){return e&&e._nodes?e._nodes:e},p.each=function(t,n,r){var i=t._nodes;i&&i.length&&e.Array.each(i,n,r||t)},p.addMethod=function(t,n,r){t&&n&&(p.prototype[t]=function(){var t=[],i=arguments;return e.Array.each(this._nodes,function(s){var o=s.uniqueID&&s.nodeType!==9?"uniqueID":"_yuid",u=e.Node._instances[s[o]],a,f;u||(u=p._getTempNode(s)),a=r||u,f=n.apply(a,i),f!==undefined&&f!==u&&(t[t.length]=f)}),t.length?t:this})},p.importMethod=function(t,n,r){typeof n=="string"?(r=r||n,p.addMethod(n,t[n])):e.Array.each(n,function(e){p.importMethod(t,e)})},p._getTempNode=function(t){var n=p._tempNode;return n||(n=e.Node.create("<div></div>"),p._tempNode=n),n._node=t,n._stateProxy=t,n},e.mix(p.prototype,{_invoke:function(e,t,n){var r=n?[]:this;return this.each(function(i){var s=i[e].apply(i,t);n&&r.push(s)}),r},item:function(t){return e.one((this._nodes||[])[t])},each:function(t,n){var r=this;return e.Array.each(this._nodes,function(i,s){return i=e.one(i),t.call(n||i,i,s,r)}),r},batch:function(t,n){var r=this;return e.Array.each(this._nodes,function(i,s){var o=e.Node._instances[i[u]];return o||(o=p._getTempNode(i)),t.call(n||o,o,s,r)}),r},some:function(t,n){var r=this;return e.Array.some(this._nodes,function(i,s){return i=e.one(i),n=n||i,t.call(n,i,s,r)})},toFrag:function(){return e.one(e.DOM._nl2frag(this._nodes))},indexOf:function(t){return e.Array.indexOf(this._nodes,e.Node.getDOMNode(t))},filter:function(t){return e.all(e.Selector.filter(this._nodes,t))},modulus:function(t,n){n=n||0;var r=[];return p.each(this,function(e,i){i%t===n&&r.push(e)}),e.all(r)},odd:function(){return this.modulus(2,1)},even:function(){return this.modulus(2)},destructor:function(){},refresh:function(){var t,n=this._nodes,r=this._query,i=this._queryRoot;return r&&(i||n&&n[0]&&n[0].ownerDocument&&(i=n[0].ownerDocument),this._nodes=e.Selector.query(r,i)),this},size:function(){return this._nodes.length},isEmpty:function(){return this._nodes.length<1},toString:function(){var e="",t=this[u]+": not bound to any nodes",n=this._nodes,i;return n&&n[0]&&(i=n[0],e+=i[r],i.id&&(e+="#"+i.id),i.className&&(e+="."+i.className.replace(" ",".")),n.length>1&&(e+="...["+n.length+" items]")),e||t},getDOMNodes:function(){return this._nodes}},!0),p.importMethod(e.Node.prototype,["destroy","empty","remove","set"]),p.prototype.get=function(t){var n=[],r=this._nodes,i=!1,s=p._getTempNode,o,u;return r[0]&&(o=e.Node._instances[r[0]._yuid]||s(r[0]),u=o._get(t),u&&u.nodeType&&(i=!0)),e.Array.each(r,function(r){o=e.Node._instances[r._yuid],o||(o=s(r)),u=o._get(t),i||(u=e.Node.scrubVal(u,o)),n.push(u)}),i?e.all(n):n},e.NodeList=p,e.all=function(e){return new p(e)},e.Node.all=e.all;var d=e.NodeList,v=Array.prototype,m={concat:1,pop:0,push:0,shift:0,slice:1,splice:1,unshift:0};e.Object.each(m,function(t,n){d.prototype[n]=function(){var r=[],i=0,s,o;while(typeof (s=arguments[i++])!="undefined")r.push(s._node||s._nodes||s);return o=v[n].apply(this._nodes,r),t?o=e.all(o):o=e.Node.scrubVal(o),o}}),e.Array.each(["removeChild","hasChildNodes","cloneNode","hasAttribute","scrollIntoView","getElementsByTagName","focus","blur","submit","reset","select","createCaption"],function(t){e.Node.prototype[t]=function(e,n,r){var i=this.invoke(t,e,n,r);return i}}),e.Node.prototype.removeAttribute=function(e){var t=this._node;return t&&t.removeAttribute(e,0),this},e.Node.importMethod(e.DOM,["contains","setAttribute","getAttribute","wrap","unwrap","generateID"]),e.NodeList.importMethod(e.Node.prototype,["getAttribute","setAttribute","removeAttribute","unwrap","wrap","generateID"])},"3.7.3",{requires:["dom-core","selector"]}),YUI.add("node-base",function(e,t){var n=["hasClass","addClass","removeClass","replaceClass","toggleClass"];e.Node.importMethod(e.DOM,n),e.NodeList.importMethod(e.Node.prototype,n);var r=e.Node,i=e.DOM;r.create=function(t,n){return n&&n._node&&(n=n._node),e.one(i.create(t,n))},e.mix(r.prototype,{create:r.create,insert:function(e,t){return this._insert(e,t),this},_insert:function(e,t){var n=this._node,r=null;return typeof t=="number"?t=this._node.childNodes[t]:t&&t._node&&(t=t._node),e&&typeof e!="string"&&(e=e._node||e._nodes||e),r=i.addHTML(n,e,t),r},prepend:function(e){return this.insert(e,0)},append:function(e){return this.insert(e,null)},appendChild:function(e){return r.scrubVal(this._insert(e))},insertBefore:function(t,n){return e.Node.scrubVal(this._insert(t,n))},appendTo:function(t){return e.one(t).append(this),this},setContent:function(e){return this._insert(e,"replace"),this},getContent:function(e){return this.get("innerHTML")}}),e.Node.prototype.setHTML=e.Node.prototype.setContent,e.Node.prototype.getHTML=e.Node.prototype.getContent,e.NodeList.importMethod(e.Node.prototype,["append","insert","appendChild","insertBefore","prepend","setContent","getContent","setHTML","getHTML"]);var r=e.Node,i=e.DOM;r.ATTRS={text:{getter:function(){return i.getText(this._node)},setter:function(e){return i.setText(this._node,e),e}},"for":{getter:function(){return i.getAttribute(this._node,"for")},setter:function(e){return i.setAttribute(this._node,"for",e),e}},options:{getter:function(){return this._node.getElementsByTagName("option")}},children:{getter:function(){var t=this._node,n=t.children,r,i,s;if(!n){r=t.childNodes,n=[];for(i=0,s=r.length;i<s;++i)r[i].tagName&&(n[n.length]=r[i])}return e.all(n)}},value:{getter:function(){return i.getValue(this._node)},setter:function(e){return i.setValue(this._node,e),e}}},e.Node.importMethod(e.DOM,["setAttribute","getAttribute"]);var r=e.Node,s=e.NodeList;r.DOM_EVENTS={abort:1,beforeunload:1,blur:1,change:1,click:1,close:1,command:1,contextmenu:1,dblclick:1,DOMMouseScroll:1,drag:1,dragstart:1,dragenter:1,dragover:1,dragleave:1,dragend:1,drop:1,error:1,focus:1,key:1,keydown:1,keypress:1,keyup:1,load:1,message:1,mousedown:1,mouseenter:1,mouseleave:1,mousemove:1,mousemultiwheel:1,mouseout:1,mouseover:1,mouseup:1,mousewheel:1,orientationchange:1,reset:1,resize:1,select:1,selectstart:1,submit:1,scroll:1,textInput:1,unload:1},e.mix(r.DOM_EVENTS,e.Env.evt.plugins),e.augment(r,e.EventTarget),e.mix(r.prototype,{purge:function(t,n){return e.Event.purgeElement(this._node,t,n),this}}),e.mix(e.NodeList.prototype,{_prepEvtArgs:function(t,n,r){var i=e.Array(arguments,0,!0);return i.length<2?i[2]=this._nodes:i.splice(2,0,this._nodes),i[3]=r||this,i},on:function(t,n,r){return e.on.apply(e,this._prepEvtArgs.apply(this,arguments))},once:function(t,n,r){return e.once.apply(e,this._prepEvtArgs.apply(this,arguments))},after:function(t,n,r){return e.after.apply(e,this._prepEvtArgs.apply(this,arguments))},onceAfter:function(t,n,r){return e.onceAfter.apply(e,this._prepEvtArgs.apply(this,arguments))}}),s.importMethod(e.Node.prototype,["detach","detachAll"]),e.mix(e.Node.ATTRS,{offsetHeight:{setter:function(t){return e.DOM.setHeight(this._node,t),t},getter:function(){return this._node.offsetHeight}},offsetWidth:{setter:function(t){return e.DOM.setWidth(this._node,t),t},getter:function(){return this._node.offsetWidth}}}),e.mix(e.Node.prototype,{sizeTo:function(t,n){var r;arguments.length<2&&(r=e.one(t),t=r.get("offsetWidth"),n=r.get("offsetHeight")),this.setAttrs({offsetWidth:t,offsetHeight:n})}});var r=e.Node;e.mix(r.prototype,{show:function(e){return e=arguments[arguments.length-1],this.toggleView(!0,e),this},_show:function(){this.setStyle("display","")},_isHidden:function(){return e.DOM.getStyle(this._node,"display")==="none"},toggleView:function(e,t){return this._toggleView.apply(this,arguments),this},_toggleView:function(e,t){return t=arguments[arguments.length-1],typeof e!="boolean"&&(e=this._isHidden()?1:0),e?this._show():this._hide(),typeof t=="function"&&t.call(this),this},hide:function(e){return e=arguments[arguments.length-1],this.toggleView(!1,e),this},_hide:function(){this.setStyle("display","none")}}),e.NodeList.importMethod(e.Node.prototype,["show","hide","toggleView"]),e.config.doc.documentElement.hasAttribute||(e.Node.prototype.hasAttribute=function(e){return e==="value"&&this.get("value")!==""?!0:!!this._node.attributes[e]&&!!this._node.attributes[e].specified}),e.Node.prototype.focus=function(){try{this._node.focus()}catch(e){}return this},e.Node.ATTRS.type={setter:function(e){if(e==="hidden")try{this._node.type="hidden"}catch(t){this.setStyle("display","none"),this._inputType="hidden"}else try{this._node.type=e}catch(t){}return e},getter:function(){return this._inputType||this._node.type},_bypassProxy:!0},e.config.doc.createElement("form").elements.nodeType&&(e.Node.ATTRS.elements={getter:function(){return this.all("input, textarea, button, select")}}),e.mix(e.Node.prototype,{_initData:function(){"_data"in this||(this._data={})},getData:function(t){this._initData();var n=this._data,r=n;return arguments.length?t in n?r=n[t]:r=this._getDataAttribute(t):typeof n=="object"&&n!==null&&(r={},e.Object.each(n,function(e,t){r[t]=e}),r=this._getDataAttributes(r)),r},_getDataAttributes:function(e){e=e||{};var t=0,n=this._node.attributes,r=n.length,i=this.DATA_PREFIX,s=i.length,o;while(t<r)o=n[t].name,o.indexOf(i)===0&&(o=o.substr(s),o in e||(e[o]=this._getDataAttribute(o))),t+=1;return e},_getDataAttribute:function(e){var e=this.DATA_PREFIX+e,t=this._node,n=t.attributes,r=n&&n[e]&&n[e].value;return r},setData:function(e,t){return this._initData(),arguments.length>1?this._data[e]=t:this._data=e,this},clearData:function(e){return"_data"in this&&(typeof e!="undefined"?delete this._data[e]:delete this._data),this}}),e.mix(e.NodeList.prototype,{getData:function(e){var t=arguments.length?[e]:[];return this._invoke("getData",t,!0)},setData:function(e,t){var n=arguments.length>1?[e,t]:[e];return this._invoke("setData",n)},clearData:function(e){var t=arguments.length?[e]:[];return this._invoke("clearData",[e])}})},"3.7.3",{requires:["event-base","node-core","dom-base"]}),function(){var e=YUI.Env;e._ready||(e._ready=function(){e.DOMReady=!0,e.remove(YUI.config.doc,"DOMContentLoaded",e._ready)},e.add(YUI.config.doc,"DOMContentLoaded",e._ready))}(),YUI.add("event-base",function(e,t){e.publish("domready",{fireOnce:!0,async:!0}),YUI.Env.DOMReady?e.fire("domready"):e.Do.before(function(){e.fire("domready")},YUI.Env,"_ready");var n=e.UA,r={},i={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9,63272:46,63273:36,63275:35},s=function(t){if(!t)return t;try{t&&3==t.nodeType&&(t=t.parentNode)}catch(n){return null}return e.one(t)},o=function(e,t,n){this._event=e,this._currentTarget=t,this._wrapper=n||r,this.init()};e.extend(o,Object,{init:function(){var e=this._event,t=this._wrapper.overrides,r=e.pageX,o=e.pageY,u,a=this._currentTarget;this.altKey=e.altKey,this.ctrlKey=e.ctrlKey,this.metaKey=e.metaKey,this.shiftKey=e.shiftKey,this.type=t&&t.type||e.type,this.clientX=e.clientX,this.clientY=e.clientY,this.pageX=r,this.pageY=o,u=e.keyCode||e.charCode,n.webkit&&u in i&&(u=i[u]),this.keyCode=u,this.charCode=u,this.which=e.which||e.charCode||u,this.button=this.which,this.target=s(e.target),this.currentTarget=s(a),this.relatedTarget=s(e.relatedTarget);if(e.type=="mousewheel"||e.type=="DOMMouseScroll")this.wheelDelta=e.detail?e.detail*-1:Math.round(e.wheelDelta/80)||(e.wheelDelta<0?-1:1);this._touch&&this._touch(e,a,this._wrapper)},stopPropagation:function(){this._event.stopPropagation(),this._wrapper.stopped=1,this.stopped=1},stopImmediatePropagation:function(){var e=this._event;e.stopImmediatePropagation?e.stopImmediatePropagation():this.stopPropagation(),this._wrapper.stopped=2,this.stopped=2},preventDefault:function(e){var t=this._event;t.preventDefault(),t.returnValue=e||!1,this._wrapper.prevented=1,this.prevented=1},halt:function(e){e?this.stopImmediatePropagation():this.stopPropagation(),this.preventDefault()}}),o.resolve=s,e.DOM2EventFacade=o,e.DOMEventFacade=o,function(){e.Env.evt.dom_wrappers={},e.Env.evt.dom_map={};var t=e.DOM,n=e.Env.evt,r=e.config,i=r.win,s=YUI.Env.add,o=YUI.Env.remove,u=function(){YUI.Env.windowLoaded=!0,e.Event._load(),o(i,"load",u)},a=function(){e.Event._unload()},f="domready",l="~yui|2|compat~",c=function(n){try{return n&&typeof n!="string"&&e.Lang.isNumber(n.length)&&!n.tagName&&!t.isWindow(n)}catch(r){return!1}},h=e.CustomEvent.prototype._delete,p=function(t){var n=h.apply(this,arguments);return this.hasSubs()||e.Event._clean(this),n},d=function(){var r=!1,u=0,h=[],v=n.dom_wrappers,m=null,g=n.dom_map;return{POLL_RETRYS:1e3,POLL_INTERVAL:40,lastError:null,_interval:null,_dri:null,DOMReady:!1,startInterval:function(){d._interval||(d._interval=setInterval(d._poll,d.POLL_INTERVAL))},onAvailable:function(t,n,r,i,s,o){var a=e.Array(t),f,l;for(f=0;f<a.length;f+=1)h.push({id:a[f],fn:n,obj:r,override:i,checkReady:s,compat:o});return u=this.POLL_RETRYS,setTimeout(d._poll,0),l=new e.EventHandle({_delete:function(){if(l.handle){l.handle.detach();return}var e,t;for(e=0;e<a.length;e++)for(t=0;t<h.length;t++)a[e]===h[t].id&&h.splice(t,1)}}),l},onContentReady:function(e,t,n,r,i){return d.onAvailable(e,t,n,r,!0,i)},attach:function(t,n,r,i){return d._attach(e.Array(arguments,0,!0))},_createWrapper:function(t,n,r,o,u){var a,f=e.stamp(t),l="event:"+f+n;return!1===u&&(l+="native"),r&&(l+="capture"),a=v[l],a||(a=e.publish(l,{silent:!0,bubbles:!1,contextFn:function(){return o?a.el:(a.nodeRef=a.nodeRef||e.one(a.el),a.nodeRef)}}),a.overrides={},a.el=t,a.key=l,a.domkey=f,a.type=n,a.fn=function(e){a.fire(d.getEvent(e,t,o||!1===u))},a.capture=r,t==i&&n=="load"&&(a.fireOnce=!0,m=l),a._delete=p,v[l]=a,g[f]=g[f]||{},g[f][l]=a,s(t,n,a.fn,r)),a},_attach:function(n,r){var s,o,u,a,f,h=!1,p,v=n[0],m=n[1],g=n[2]||i,y=r&&r.facade,b=r&&r.capture,w=r&&r.overrides;n[n.length-1]===l&&(s=!0);if(!m||!m.call)return!1;if(c(g))return o=[],e.each(g,function(e,t){n[2]=e,o.push(d._attach(n.slice(),r))}),new e.EventHandle(o);if(e.Lang.isString(g)){if(s)u=t.byId(g);else{u=e.Selector.query(g);switch(u.length){case 0:u=null;break;case 1:u=u[0];break;default:return n[2]=u,d._attach(n,r)}}if(!u)return p=d.onAvailable(g,function(){p.handle=d._attach(n,r)},d,!0,!1,s),p;g=u}return g?(e.Node&&e.instanceOf(g,e.Node)&&(g=e.Node.getDOMNode(g)),a=d._createWrapper(g,v,b,s,y),w&&e.mix(a.overrides,w),g==i&&v=="load"&&YUI.Env.windowLoaded&&(h=!0),s&&n.pop(),f=n[3],p=a._on(m,f,n.length>4?n.slice(4):null),h&&a.fire(),p):!1},detach:function(n,r,i,s){var o=e.Array(arguments,0,!0),u,a,f,h,p,m;o[o.length-1]===l&&(u=!0);if(n&&n.detach)return n.detach();typeof i=="string"&&(u?i=t.byId(i):(i=e.Selector.query(i),a=i.length,a<1?i=null:a==1&&(i=i[0])));if(!i)return!1;if(i.detach)return o.splice(2,1),i.detach.apply(i,o);if(c(i)){f=!0;for(h=0,a=i.length;h<a;++h)o[2]=i[h],f=e.Event.detach.apply(e.Event,o)&&f;return f}return!n||!r||!r.call?d.purgeElement(i,!1,n):(p="event:"+e.stamp(i)+n,m=v[p],m?m.detach(r):!1)},getEvent:function(t,n,r){var s=t||i.event;return r?s:new e.DOMEventFacade(s,n,v["event:"+e.stamp(n)+t.type])},generateId:function(e){return t.generateID(e)},_isValidCollection:c,_load:function(t){r||(r=!0,e.fire&&e.fire(f),d._poll())},_poll:function(){if(d.locked)return;if(e.UA.ie&&!YUI.Env.DOMReady){d.startInterval();return}d.locked=!0;var n,i,s,o,a,f,l=!r;l||(l=u>0),a=[],f=function(t,n){var r,i=n.override;try{n.compat?(n.override?i===!0?r=n.obj:r=i:r=t,n.fn.call(r,n.obj)):(r=n.obj||e.one(t),n.fn.apply(r,e.Lang.isArray(i)?i:[]))}catch(s){}};for(n=0,i=h.length;n<i;++n)s=h[n],s&&!s.checkReady&&(o=s.compat?t.byId(s.id):e.Selector.query(s.id,null,!0),o?(f(o,s),h[n]=null):a.push(s));for(n=0,i=h.length;n<i;++n){s=h[n];if(s&&s.checkReady){o=s.compat?t.byId(s.id):e.Selector.query(s.id,null,!0);if(o){if(r||o.get&&o.get("nextSibling")||o.nextSibling)f(o,s),h[n]=null}else a.push(s)}}u=a.length===0?0:u-1,l?d.startInterval():(clearInterval(d._interval),d._interval=null),d.locked=!1;return},purgeElement:function(t,n,r){var i=e.Lang.isString(t)?e.Selector.query(t,null,!0):t,s=d.getListeners(i,r),o,u,a,f;if(n&&i){s=s||[],a=e.Selector.query("*",i),u=a.length;for(o=0;o<u;++o)f=d.getListeners(a[o],r),f&&(s=s.concat(f))}if(s)for(o=0,u=s.length;o<u;++o)s[o].detachAll()},_clean:function(t){var n=t.key,r=t.domkey;o(t.el,t.type,t.fn,t.capture),delete v[n],delete e._yuievt.events[n],g[r]&&(delete g[r][n],e.Object.size(g[r])||delete g[r])},getListeners:function(t,r){var i=e.stamp(t,!0),s=g[i],o=[],u=r?"event:"+i+r:null,a=n.plugins;return s?(u?(a[r]&&a[r].eventDef&&(u+="_synth"),s[u]&&o.push(s[u]),u+="native",s[u]&&o.push(s[u])):e.each(s,function(e,t){o.push(e)}),o.length?o:null):null},_unload:function(t){e.each(v,function(e,n){e.type=="unload"&&e.fire(t),e.detachAll()}),o(i,"unload",a)},nativeAdd:s,nativeRemove:o}}();e.Event=d,r.injected||YUI.Env.windowLoaded?u():s(i,"load",u),e.UA.ie&&e.on(f,d._poll);try{s(i,"unload",a)}catch(v){}d.Custom=e.CustomEvent,d.Subscriber=e.Subscriber,d.Target=e.EventTarget,d.Handle=e.EventHandle,d.Facade=e.EventFacade,d._poll()}(),e.Env.evt.plugins.available={on:function(t,n,r,i){var s=arguments.length>4?e.Array(arguments,4,!0):null;return e.Event.onAvailable.call(e.Event,r,n,i,s)}},e.Env.evt.plugins.contentready={on:function(t,n,r,i){var s=arguments.length>4?e.Array(arguments,4,!0):null;return e.Event.onContentReady.call(e.Event,r,n,i,s)}}},"3.7.3",{requires:["event-custom-base"]}),YUI.add("pluginhost-base",function(e,t){function r(){this._plugins={}}var n=e.Lang;r.prototype={plug:function(e,t){var r,i,s;if(n.isArray(e))for(r=0,i=e.length;r<i;r++)this.plug(e[r]);else e&&!n.isFunction(e)&&(t=e.cfg,e=e.fn),e&&e.NS&&(s=e.NS,t=t||{},t.host=this,this.hasPlugin(s)?this[s].setAttrs&&this[s].setAttrs(t):(this[s]=new e(t),this._plugins[s]=e));return this},unplug:function(e){var t=e,r=this._plugins;if(e)n.isFunction(e)&&(t=e.NS,t&&(!r[t]||r[t]!==e)&&(t=null)),t&&(this[t]&&(this[t].destroy&&this[t].destroy(),delete this[t]),r[t]&&delete r[t]);else for(t in this._plugins)this._plugins.hasOwnProperty(t)&&this.unplug(t);return this},hasPlugin:function(e){return this._plugins[e]&&this[e]},_initPlugins:function(e){this._plugins=this._plugins||{},this._initConfigPlugins&&this._initConfigPlugins(e)},_destroyPlugins:function(){this.unplug()}},e.namespace("Plugin").Host=r},"3.7.3",{requires:["yui-base"]}),YUI.add("pluginhost-config",function(e,t){var n=e.Plugin.Host,r=e.Lang;n.prototype._initConfigPlugins=function(t){var n=this._getClasses?this._getClasses():[this.constructor],r=[],i={},s,o,u,a,f;for(o=n.length-1;o>=0;o--)s=n[o],a=s._UNPLUG,a&&e.mix(i,a,!0),u=s._PLUG,u&&e.mix(r,u,!0);for(f in r)r.hasOwnProperty(f)&&(i[f]||this.plug(r[f]));t&&t.plugins&&this.plug(t.plugins)},n.plug=function(t,n,i){var s,o,u,a;if(t!==e.Base){t._PLUG=t._PLUG||{},r.isArray(n)||(i&&(n={fn:n,cfg:i}),n=[n]);for(o=0,u=n.length;o<u;o++)s=n[o],a=s.NAME||s.fn.NAME,t._PLUG[a]=s}},n.unplug=function(t,n){var i,s,o,u;if(t!==e.Base){t._UNPLUG=t._UNPLUG||{},r.isArray(n)||(n=[n]);for(s=0,o=n.length;s<o;s++)i=n[s],u=i.NAME,t._PLUG[u]?delete t._PLUG[u]:t._UNPLUG[u]=i}}},"3.7.3",{requires:["pluginhost-base"]}),YUI.add("event-delegate",function(e,t){function f(t,r,u,l){var c=n(arguments,0,!0),h=i(u)?u:null,p,d,v,m,g,y,b,w,E;if(s(t)){w=[];if(o(t))for(y=0,b=t.length;y<b;++y)c[0]=t[y],w.push(e.delegate.apply(e,c));else{c.unshift(null);for(y in t)t.hasOwnProperty(y)&&(c[0]=y,c[1]=t[y],w.push(e.delegate.apply(e,c)))}return new e.EventHandle(w)}p=t.split(/\|/),p.length>1&&(g=p.shift(),c[0]=t=p.shift()),d=e.Node.DOM_EVENTS[t],s(d)&&d.delegate&&(E=d.delegate.apply(d,arguments));if(!E){if(!t||!r||!u||!l)return;v=h?e.Selector.query(h,null,!0):u,!v&&i(u)&&(E=e.on("available",function(){e.mix(E,e.delegate.apply(e,c),!0)},u)),!E&&v&&(c.splice(2,2,v),E=e.Event._attach(c,{facade:!1}),E.sub.filter=l,E.sub._notify=f.notifySub)}return E&&g&&(m=a[g]||(a[g]={}),m=m[t]||(m[t]=[]),m.push(E)),E}var n=e.Array,r=e.Lang,i=r.isString,s=r.isObject,o=r.isArray,u=e.Selector.test,a=e.Env.evt.handles;f.notifySub=function(t,r,i){r=r.slice(),this.args&&r.push.apply(r,this.args);var s=f._applyFilter(this.filter,r,i),o,u,a,l;if(s){s=n(s),o=r[0]=new e.DOMEventFacade(r[0],i.el,i),o.container=e.one(i.el);for(u=0,a=s.length;u<a&&!o.stopped;++u){o.currentTarget=e.one(s[u]),l=this.fn.apply(this.context||o.currentTarget,r);if(l===!1)break}return l}},f.compileFilter=e.cached(function(e){return function(t,n){return u(t._node,e,n.currentTarget===n.target?null:n.currentTarget._node)}}),f._applyFilter=function(t,n,r){var s=n[0],o=r.el,a=s.target||s.srcElement,f=[],l=!1;a.nodeType===3&&(a=a.parentNode),n.unshift(a);if(i(t))while(a){l=a===o,u(a,t,l?null:o)&&f.push(a);if(l)break;a=a.parentNode}else{n[0]=e.one(a),n[1]=new e.DOMEventFacade(s,o,r);while(a){t.apply(n[0],n)&&f.push(a);if(a===o)break;a=a.parentNode,n[0]=e.one(a)}n[1]=s}return f.length<=1&&(f=f[0]),n.shift(),f},e.delegate=e.Event.delegate=f},"3.7.3",{requires:["node-base"]}),YUI.add("node-event-delegate",function(e,t){e.Node.prototype.delegate=function(t){var n=e.Array(arguments,0,!0),r=e.Lang.isObject(t)&&!e.Lang.isArray(t)?1:2;return n.splice(r,0,this._node),e.delegate.apply(e,n)}},"3.7.3",{requires:["node-base","event-delegate"]}),YUI.add("node-pluginhost",function(e,t){e.Node.plug=function(){var t=e.Array(arguments);return t.unshift(e.Node),e.Plugin.Host.plug.apply(e.Base,t),e.Node},e.Node.unplug=function(){var t=e.Array(arguments);return t.unshift(e.Node),e.Plugin.Host.unplug.apply(e.Base,t),e.Node},e.mix(e.Node,e.Plugin.Host,!1,null,1),e.NodeList.prototype.plug=function(){var t=arguments;return e.NodeList.each(this,function(n){e.Node.prototype.plug.apply(e.one(n),t)}),this},e.NodeList.prototype.unplug=function(){var t=arguments;return e.NodeList.each(this,function(n){e.Node.prototype.unplug.apply(e.one(n),t)}),this}},"3.7.3",{requires:["node-base","pluginhost"]}),YUI.add("node-screen",function(e,t){e.each(["winWidth","winHeight","docWidth","docHeight","docScrollX","docScrollY"],function(t){e.Node.ATTRS[t]={getter:function(){var n=Array.prototype.slice.call(arguments);return n.unshift(e.Node.getDOMNode(this)),e.DOM[t].apply(this,n)}}}),e.Node.ATTRS.scrollLeft={getter:function(){var t=e.Node.getDOMNode(this);return"scrollLeft"in t?t.scrollLeft:e.DOM.docScrollX(t)},setter:function(t){var n=e.Node.getDOMNode(this);n&&("scrollLeft"in n?n.scrollLeft=t:(n.document||n.nodeType===9)&&e.DOM._getWin(n).scrollTo(t,e.DOM.docScrollY(n)))}},e.Node.ATTRS.scrollTop={getter:function(){var t=e.Node.getDOMNode(this);return"scrollTop"in t?t.scrollTop:e.DOM.docScrollY(t)},setter:function(t){var n=e.Node.getDOMNode(this);n&&("scrollTop"in n?n.scrollTop=t:(n.document||n.nodeType===9)&&e.DOM._getWin(n).scrollTo(e.DOM.docScrollX(n),t))}},e.Node.importMethod(e.DOM,["getXY","setXY","getX","setX","getY","setY","swapXY"]),e.Node.ATTRS.region={getter:function(){var t=this.getDOMNode(),n;return t&&!t.tagName&&t.nodeType===9&&(t=t.documentElement),e.DOM.isWindow(t)?n=e.DOM.viewportRegion(t):n=e.DOM.region(t),n}},e.Node.ATTRS.viewportRegion={getter:function(){return e.DOM.viewportRegion(e.Node.getDOMNode(this))}},e.Node.importMethod(e.DOM,"inViewportRegion"),e.Node.prototype.intersect=function(t,n){var r=e.Node.getDOMNode(this);return e.instanceOf(t,e.Node)&&(t=e.Node.getDOMNode(t)),e.DOM.intersect(r,t,n)},e.Node.prototype.inRegion=function(t,n,r){var i=e.Node.getDOMNode(this);return e.instanceOf(t,e.Node)&&(t=e.Node.getDOMNode(t)),e.DOM.inRegion(i,t,n,r)}},"3.7.3",{requires:["dom-screen","node-base"]}),YUI.add("node-style",function(e,t){(function(e){e.mix(e.Node.prototype,{setStyle:function(t,n){return e.DOM.setStyle(this._node,t,n),this},setStyles:function(t){return e.DOM.setStyles(this._node,t),this},getStyle:function(t){return e.DOM.getStyle(this._node,t)},getComputedStyle:function(t){return e.DOM.getComputedStyle(this._node,t)}}),e.NodeList.importMethod(e.Node.prototype,["getStyle","getComputedStyle","setStyle","setStyles"])})(e)},"3.7.3",{requires:["dom-style","node-base"]}),YUI.add("querystring-stringify-simple",function(e,t){var n=e.namespace("QueryString"),r=encodeURIComponent;n.stringify=function(t,n){var i=[],s=n&&n.arrayKey?!0:!1,o,u,a;for(o in t)if(t.hasOwnProperty(o))if(e.Lang.isArray(t[o]))for(u=0,a=t[o].length;u<a;u++)i.push(r(s?o+"[]":o)+"="+r(t[o][u]));else i.push(r(o)+"="+r(t[o]));return i.join("&")}},"3.7.3",{requires:["yui-base"]}),YUI.add("io-base",function(e,t){function o(t){var n=this;n._uid="io:"+s++,n._init(t),e.io._map[n._uid]=n}var n=["start","complete","end","success","failure","progress"],r=["status","statusText","responseText","responseXML"],i=e.config.win,s=0;o.prototype={_id:0,_headers:{"X-Requested-With":"XMLHttpRequest"},_timeout:{},_init:function(t){var r=this,i,s;r.cfg=t||{},e.augment(r,e.EventTarget);for(i=0,s=n.length;i<s;++i)r.publish("io:"+n[i],e.merge({broadcast:1},t)),r.publish("io-trn:"+n[i],t)},_create:function(t,n){var r=this,s={id:e.Lang.isNumber(n)?n:r._id++,uid:r._uid},o=t.xdr?t.xdr.use:null,u=t.form&&t.form.upload?"iframe":null,a;return o==="native"&&(o=e.UA.ie&&!l?"xdr":null,r.setHeader("X-Requested-With")),a=o||u,s=a?e.merge(e.IO.customTransport(a),s):e.merge(e.IO.defaultTransport(),s),s.notify&&(t.notify=function(e,t,n){r.notify(e,t,n)}),a||i&&i.FormData&&t.data instanceof i.FormData&&(s.c.upload.onprogress=function(e){r.progress(s,e,t)},s.c.onload=function(e){r.load(s,e,t)},s.c.onerror=function(e){r.error(s,e,t)},s.upload=!0),s},_destroy:function(t){i&&!t.notify&&!t.xdr&&(u&&!t.upload?t.c.onreadystatechange=null:t.upload?(t.c.upload.onprogress=null,t.c.onload=null,t.c.onerror=null):e.UA.ie&&!t.e&&t.c.abort()),t=t.c=null},_evt:function(t,r,i){var s=this,o,u=i.arguments,a=s.cfg.emitFacade,f="io:"+t,l="io-trn:"+t;this.detach(l),r.e&&(r.c={status:0,statusText:r.e}),o=[a?{id:r.id,data:r.c,cfg:i,arguments:u}:r.id],a||(t===n[0]||t===n[2]?u&&o.push(u):(r.evt?o.push(r.evt):o.push(r.c),u&&o.push(u))),o.unshift(f),s.fire.apply(s,o),i.on&&(o[0]=l,s.once(l,i.on[t],i.context||e),s.fire.apply(s,o))},start:function(e,t){this._evt(n[0],e,t)},complete:function(e,t){this._evt(n[1],e,t)},end:function(e,t){this._evt(n[2],e,t),this._destroy(e)},success:function(e,t){this._evt(n[3],e,t),this.end(e,t)},failure:function(e,t){this._evt(n[4],e,t),this.end(e,t)},progress:function(e,t,r){e.evt=t,this._evt(n[5],e,r)},load:function(e,t,r){e.evt=t.target,this._evt(n[1],e,r)},error:function(e,t,r){e.evt=t,this._evt(n[4],e,r)},_retry:function(e,t,n){return this._destroy(e),n.xdr.use="flash",this.send(t,n,e.id)},_concat:function(e,t){return e+=(e.indexOf("?")===-1?"?":"&")+t,e},setHeader:function(e,t){t?this._headers[e]=t:delete this._headers[e]},_setHeaders:function(t,n){n=e.merge(this._headers,n),e.Object.each(n,function(e,r){e!=="disable"&&t.setRequestHeader(r,n[r])})},_startTimeout:function(e,t){var n=this;n._timeout[e.id]=setTimeout(function(){n._abort(e,"timeout")},t)},_clearTimeout:function(e){clearTimeout(this._timeout[e]),delete this._timeout[e]},_result:function(e,t){var n;try{n=e.c.status}catch(r){n=0}n>=200&&n<300||n===304||n===1223?this.success(e,t):this.failure(e,t)},_rS:function(e,t){var n=this;e.c.readyState===4&&(t.timeout&&n._clearTimeout(e.id),setTimeout(function(){n.complete(e,t),n._result(e,t)},0))},_abort:function(e,t){e&&e.c&&(e.e=t,e.c.abort())},send:function(t,n,i){var s,o,u,a,f,c,h=this,p=t,d={};n=n?e.Object(n):{},s=h._create(n,i),o=n.method?n.method.toUpperCase():"GET",f=n.sync,c=n.data,e.Lang.isObject(c)&&!c.nodeType&&!s.upload&&(c=e.QueryString.stringify(c));if(n.form){if(n.form.upload)return h.upload(s,t,n);c=h._serialize(n.form,c)}if(c)switch(o){case"GET":case"HEAD":case"DELETE":p=h._concat(p,c),c="";break;case"POST":case"PUT":n.headers=e.merge({"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},n.headers)}if(s.xdr)return h.xdr(p,s,n);if(s.notify)return s.c.send(s,t,n);!f&&!s.upload&&(s.c.onreadystatechange=function(){h._rS(s,n)});try{s.c.open(o,p,!f,n.username||null,n.password||null),h._setHeaders(s.c,n.headers||{}),h.start(s,n),n.xdr&&n.xdr.credentials&&l&&(s.c.withCredentials=!0),s.c.send(c);if(f){for(u=0,a=r.length;u<a;++u)d[r[u]]=s.c[r[u]];return d.getAllResponseHeaders=function(){return s.c.getAllResponseHeaders()},d.getResponseHeader=function(e){return s.c.getResponseHeader(e)},h.complete(s,n),h._result(s,n),d}}catch(v){if(s.xdr)return h._retry(s,t,n);h.complete(s,n),h._result(s,n)}return n.timeout&&h._startTimeout(s,n.timeout),{id:s.id,abort:function(){return s.c?h._abort(s,"abort"):!1},isInProgress:function(){return s.c?s.c.readyState%4:!1},io:h}}},e.io=function(t,n){var r=e.io._map["io:0"]||new o;return r.send.apply(r,[t,n])},e.io.header=function(t,n){var r=e.io._map["io:0"]||new o;r.setHeader(t,n)},e.IO=o,e.io._map={};var u=i&&i.XMLHttpRequest,a=i&&i.XDomainRequest,f=i&&i.ActiveXObject,l=u&&"withCredentials"in new XMLHttpRequest;e.mix(e.IO,{_default:"xhr",defaultTransport:function(t){if(!t){var n={c:e.IO.transports[e.IO._default](),notify:e.IO._default==="xhr"?!1:!0};return n}e.IO._default=t},transports:{xhr:function(){return u?new XMLHttpRequest:f?new ActiveXObject("Microsoft.XMLHTTP"):null},xdr:function(){return a?new XDomainRequest:null},iframe:function(){return{}},flash:null,nodejs:null},customTransport:function(t){var n={c:e.IO.transports[t]()};return n[t==="xdr"||t==="flash"?"xdr":"notify"]=!0,n}}),e.mix(e.IO.prototype,{notify:function(e,t,n){var r=this;switch(e){case"timeout":case"abort":case"transport error":t.c={status:0,statusText:e},e="failure";default:r[e].apply(r,[t,n])}}})},"3.7.3",{requires:["event-custom-base","querystring-stringify-simple"]}),YUI.add("json-parse",function(Y,NAME){function fromGlobal(e){var t=typeof global=="object"?global:undefined;return(Y.UA.nodejs&&t?t:Y.config.win||{})[e]}function workingNative(e,t){return e==="ok"?!0:t}var _JSON=fromGlobal("JSON"),Native=Object.prototype.toString.call(_JSON)==="[object JSON]"&&_JSON,useNative=!!Native,_UNICODE_EXCEPTIONS=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_ESCAPES=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,_VALUES=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,_BRACKETS=/(?:^|:|,)(?:\s*\[)+/g,_UNSAFE=/[^\],:{}\s]/,_escapeException=function(e){return"\\u"+("0000"+(+e.charCodeAt(0)).toString(16)).slice(-4)},_revive=function(e,t){var n=function(e,r){var i,s,o=e[r];if(o&&typeof o=="object")for(i in o)o.hasOwnProperty(i)&&(s=n(o,i),s===undefined?delete o[i]:o[i]=s);return t.call(e,r,o)};return typeof t=="function"?n({"":e},""):e},_parse=function(s,reviver){s=s.replace(_UNICODE_EXCEPTIONS,_escapeException);if(!_UNSAFE.test(s.replace(_ESCAPES,"@").replace(_VALUES,"]").replace(_BRACKETS,"")))return _revive(eval("("+s+")"),reviver);throw new SyntaxError("JSON.parse")};Y.namespace("JSON").parse=function(e,t){return typeof e!="string"&&(e+=""),Native&&Y.JSON.useNativeParse?Native.parse(e,t):_parse(e,t)};if(Native)try{useNative=Native.parse('{"ok":false}',workingNative).ok}catch(e){useNative=!1}Y.JSON.useNativeParse=useNative},"3.7.3",{requires:["yui-base"]}),YUI.add("transition",function(e,t){var n="",r="",i=e.config.doc,s="documentElement",o="transition",u="transition",a="transitionProperty",f="transform",l,c,h,p,d,v,m={},g=["Webkit","Moz"],y={Webkit:"webkitTransitionEnd"},b=function(){this.init.apply(this,arguments)};b._toCamel=function(e){return e=e.replace(/-([a-z])/gi,function(e,t){return t.toUpperCase()}),e},b._toHyphen=function(e){return e=e.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g,function(e,t,n,r){var i=(t?"-"+t.toLowerCase():"")+n;return r&&(i+="-"+r.toLowerCase()),i}),e},b.SHOW_TRANSITION="fadeIn",b.HIDE_TRANSITION="fadeOut",b.useNative=!1,"transition"in i[s].style?(b.useNative=!0,b.supported=!0):e.Array.each(g,function(e){var t=e+"Transition";t in i[s].style&&(n=e,r=b._toHyphen(e)+"-",b.useNative=!0,b.supported=!0,b._VENDOR_PREFIX=e)}),n&&(u=n+"Transition",a=n+"TransitionProperty",f=n+"Transform"),l=r+"transition-property",c=r+"transition-duration",h=r+"transition-timing-function",p=r+"transition-delay",d="transitionend",v="on"+n.toLowerCase()+"transitionend",d=y[n]||d,b.fx={},b.toggles={},b._hasEnd={},b._reKeywords=/^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i,e.Node.DOM_EVENTS[d]=1,b.NAME="transition",b.DEFAULT_EASING="ease",b.DEFAULT_DURATION=.5,b.DEFAULT_DELAY=0,b._nodeAttrs={},b.prototype={constructor:b,init:function(e,t){var n=this;return n._node=e,!n._running&&t&&(n._config=t,e._transition=n,n._duration="duration"in t?t.duration:n.constructor.DEFAULT_DURATION,n._delay="delay"in t?t.delay:n.constructor.DEFAULT_DELAY,n._easing=t.easing||n.constructor.DEFAULT_EASING,n._count=0,n._running=!1),n},addProperty:function(t,n){var r=this,i=this._node,s=e.stamp(i),o=e.one(i),u=b._nodeAttrs[s],a,f,l,c,h;u||(u=b._nodeAttrs[s]={}),c=u[t],n&&n.value!==undefined?h=n.value:n!==undefined&&(h=n,n=m),typeof h=="function"&&(h=h.call(o,o)),c&&c.transition&&c.transition!==r&&c.transition._count--,r._count++,l=(typeof n.duration!="undefined"?n.duration:r._duration)||1e-4,u[t]={value:h,duration:l,delay:typeof n.delay!="undefined"?n.delay:r._delay,easing:n.easing||r._easing,transition:r},a=e.DOM.getComputedStyle(i,t),f=typeof h=="string"?a:parseFloat(a),b.useNative&&f===h&&setTimeout(function(){r._onNativeEnd.call(i,{propertyName:t,elapsedTime:l})},l*1e3)},removeProperty:function(t){var n=this,r=b._nodeAttrs[e.stamp(n._node)];r&&r[t]&&(delete r[t],n._count--)},initAttrs:function(t){var n,r=this._node;t.transform&&!t[f]&&(t[f]=t.transform,delete t.transform);for(n in t)t.hasOwnProperty(n)&&!b._reKeywords.test(n)&&(this.addProperty(n,t[n]),r.style[n]===""&&e.DOM.setStyle(r,n,e.DOM.getComputedStyle(r,n)))},run:function(t){var n=this,r=n._node,i=n._config,s={type:"transition:start",config:i};return n._running||(n._running=!0,i.on&&i.on.start&&i.on.start.call(e.one(r),s),n.initAttrs(n._config),n._callback=t,n._start()),n},_start:function(){this._runNative()},_prepDur:function(e){return e=parseFloat(e),e+"s"},_runNative:function(t){var n=this,r=n._node,i=e.stamp(r),s=r.style,o=r.ownerDocument.defaultView.getComputedStyle(r),u=b._nodeAttrs[i],a="",f=o[b._toCamel(l)],v=l+": ",m=c+": ",g=h+": ",y=p+": ",w,E,S;f!=="all"&&(v+=f+",",m+=o[b._toCamel(c)]+",",g+=o[b._toCamel(h)]+",",y+=o[b._toCamel(p)]+",");for(S in u)w=b._toHyphen(S),E=u[S],(E=u[S])&&E.transition===n&&(S in r.style?(m+=n._prepDur(E.duration)+",",y+=n._prepDur(E.delay)+",",g+=E.easing+",",v+=w+",",a+=w+": "+E.value+"; "):this.removeProperty(S));v=v.replace(/,$/,";"),m=m.replace(/,$/,";"),g=g.replace(/,$/,";"),y=y.replace(/,$/,";"),b._hasEnd[i]||(r.addEventListener(d,n._onNativeEnd,""),b._hasEnd[i]=!0),s.cssText+=v+m+g+y+a},_end:function(t){var n=this,r=n._node,i=n._callback,s=n._config,o={type:"transition:end",config:s,elapsedTime:t},u=e.one(r);n._running=!1,n._callback=null,r&&(s.on&&s.on.end?setTimeout(function(){s.on.end.call(u,o),i&&i.call(u,o)},1):i&&setTimeout(function(){i.call(u,o)},1))},_endNative:function(e){var t=this._node,n=t.ownerDocument.defaultView.getComputedStyle(t,"")[b._toCamel(l)];e=b._toHyphen(e),typeof n=="string"&&(n=n.replace(new RegExp("(?:^|,\\s)"+e+",?"),","),n=n.replace(/^,|,$/,""),t.style[u]=n)},_onNativeEnd:function(t){var n=this,r=e.stamp(n),i=t,s=b._toCamel(i.propertyName),o=i.elapsedTime,u=b._nodeAttrs[r],f=u[s],l=f?f.transition:null,c,h;l&&(l.removeProperty(s),l._endNative(s),h=l._config[s],c={type:"propertyEnd",propertyName:s,elapsedTime:o,config:h},h&&h.on&&h.on.end&&h.on.end.call(e.one(n),c),l._count<=0&&(l._end(o),n.style[a]=""))},destroy:function(){var e=this,t=e._node;t&&(t.removeEventListener(d,e._onNativeEnd,!1),e._node=null)}},e.Transition=b,e.TransitionNative=b,e.Node.prototype.transition=function(t,n,r){var i=b._nodeAttrs[e.stamp(this._node)],s=i?i.transition||null:null,o,u;if(typeof t=="string"){typeof n=="function"&&(r=n,n=null),o=b.fx[t];if(n&&typeof n!="boolean"){n=e.clone(n);for(u in o)o.hasOwnProperty(u)&&(u in n||(n[u]=o[u]))}else n=o}else r=n,n=t;return s&&!s._running?s.init(this,n):s=new b(this._node,n),s.run(r),this},e.Node.prototype.show=function(t,n,r){return this._show(),t&&e.Transition&&(typeof t!="string"&&!t.push&&(typeof n=="function"&&(r=n,n=t),t=b.SHOW_TRANSITION),this.transition(t,n,r)),this};var w=function(e,t,n){return function(){t&&t.call(e),n&&n.apply(e._node,arguments)}};e.Node.prototype.hide=function(t,n,r){return t&&e.Transition?(typeof n=="function"&&(r=n,n=null),r=w(this,this._hide,r),typeof t!="string"&&!t.push&&(typeof n=="function"&&(r=n,n=t),t=b.HIDE_TRANSITION),this.transition(t,n,r)):this._hide(),this},e.NodeList.prototype.transition=function(t,n){var r=this._nodes,i=0,s;while(s=r[i++])e.one(s).transition(t,n);return this},e.Node.prototype.toggleView=function(t,n,r){return this._toggles=this._toggles||[],r=arguments[arguments.length-1],typeof t=="boolean"&&(n=t,t=null),t=t||e.Transition.DEFAULT_TOGGLE,typeof n=="undefined"&&t in this._toggles&&(n=!this._toggles[t]),n=n?1:0,n?this._show():r=w(this,this._hide,r),this._toggles[t]=n,this.transition(e.Transition.toggles[t][n],r),this},e.NodeList.prototype.toggleView=function(t,n,r){var i=this._nodes,s=0,o;while(o=i[s++])e.one(o).toggleView(t,n,r);return this},e.mix(b.fx,{fadeOut:{opacity:0,duration:.5,easing:"ease-out"},fadeIn:{opacity:1,duration:.5,easing:"ease-in"},sizeOut:{height:0,width:0,duration:.75,easing:"ease-out"},sizeIn:{height:function(e){return e.get("scrollHeight")+"px"},width:function(e){return e.get("scrollWidth")+"px"},duration:.5,easing:"ease-in",on:{start:function(){var e=this.getStyle("overflow");e!=="hidden"&&(this.setStyle("overflow","hidden"),this._transitionOverflow=e)},end:function(){this._transitionOverflow&&(this.setStyle("overflow",this._transitionOverflow),delete this._transitionOverflow)}}}}),e.mix(b.toggles,{size:["sizeOut","sizeIn"],fade:["fadeOut","fadeIn"]}),b.DEFAULT_TOGGLE="fade"},"3.7.3",{requires:["node-style"]}),YUI.add("selector-css2",function(e,t){var n="parentNode",r="tagName",i="attributes",s="combinator",o="pseudos",u=e.Selector,a={_reRegExpTokens:/([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,SORT_RESULTS:!0,_isXML:function(){var t=e.config.doc.createElement("div").tagName!=="DIV";return t}(),shorthand:{"\\#(-?[_a-z0-9]+[-\\w\\uE000]*)":"[id=$1]","\\.(-?[_a-z]+[-\\w\\uE000]*)":"[className~=$1]"},operators:{"":function(t,n){return e.DOM.getAttribute(t,n)!==""},"~=":"(?:^|\\s+){val}(?:\\s+|$)","|=":"^{val}-?"},pseudos:{"first-child":function(t){return e.DOM._children(t[n])[0]===t}},_bruteQuery:function(t,n,r){var i=[],s=[],o=u._tokenize(t),a=o[o.length-1],f=e.DOM._getDoc(n),l,c,h,p;if(a){c=a.id,h=a.className,p=a.tagName||"*";if(n.getElementsByTagName)c&&(n.all||n.nodeType===9||e.DOM.inDoc(n))?s=e.DOM.allById(c,n):h?s=n.getElementsByClassName(h):s=n.getElementsByTagName(p);else{l=n.firstChild;while(l)l.tagName&&(p==="*"||l.tagName===p)&&s.push(l),l=l.nextSibling||l.firstChild}s.length&&(i=u._filterNodes(s,o,r))}return i},_filterNodes:function(t,n,r){var i=0,s,o=n.length,a=o-1,f=[],l=t[0],c=l,h=e.Selector.getters,p,d,v,m,g,y,b,w;for(i=0;c=l=t[i++];){a=o-1,m=null;e:while(c&&c.tagName){v=n[a],b=v.tests,s=b.length;if(s&&!g)while(w=b[--s]){p=w[1],h[w[0]]?y=h[w[0]](c,w[0]):(y=c[w[0]],w[0]==="tagName"&&!u._isXML&&(y=y.toUpperCase()),typeof y!="string"&&y!==undefined&&y.toString?y=y.toString():y===undefined&&c.getAttribute&&(y=c.getAttribute(w[0],2)));if(p==="="&&y!==w[2]||typeof p!="string"&&p.test&&!p.test(y)||!p.test&&typeof p=="function"&&!p(c,w[0],w[2])){if(c=c[m])while(c&&(!c.tagName||v.tagName&&v.tagName!==c.tagName))c=c[m];continue e}}a--;if(!!g||!(d=v.combinator)){f.push(l);if(r)return f;break}m=d.axis,c=c[m];while(c&&!c.tagName)c=c[m];d.direct&&(m=null)}}return l=c=null,f},combinators:{" ":{axis:"parentNode"},">":{axis:"parentNode",direct:!0},"+":{axis:"previousSibling",direct:!0}},_parsers:[{name:i,re:/^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,fn:function(t,n){var r=t[2]||"",i=u.operators,s=t[3]?t[3].replace(/\\/g,""):"",o;if(t[1]==="id"&&r==="="||t[1]==="className"&&e.config.doc.documentElement.getElementsByClassName&&(r==="~="||r==="="))n.prefilter=t[1],t[3]=s,n[t[1]]=t[1]==="id"?t[3]:s;r in i&&(o=i[r],typeof o=="string"&&(t[3]=s.replace(u._reRegExpTokens,"\\$1"),o=new RegExp(o.replace("{val}",t[3]))),t[2]=o);if(!n.last||n.prefilter!==t[1])return t.slice(1)}},{name:r,re:/^((?:-?[_a-z]+[\w-]*)|\*)/i,fn:function(e,t){var n=e[1];u._isXML||(n=n.toUpperCase()),t.tagName=n;if(n!=="*"&&(!t.last||t.prefilter))return[r,"=",n];t.prefilter||(t.prefilter="tagName")}},{name:s,re:/^\s*([>+~]|\s)\s*/,fn:function(e,t){}},{name:o,re:/^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,fn:function(e,t){var n=u[o][e[1]];return n?(e[2]&&(e[2]=e[2].replace(/\\/g,"")),[e[2],n]):!1}}],_getToken:function(e){return{tagName:null,id:null,className:null,attributes:{},combinator:null,tests:[]}},_tokenize:function(t){t=t||"",t=u._parseSelector(e.Lang.trim(t));var n=u._getToken(),r=t,i=[],o=!1,a,f,l,c;e:do{o=!1;for(l=0;c=u._parsers[l++];)if(a=c.re.exec(t)){c.name!==s&&(n.selector=t),t=t.replace(a[0],""),t.length||(n.last=!0),u._attrFilters[a[1]]&&(a[1]=u._attrFilters[a[1]]),f=c.fn(a,n);if(f===!1){o=!1;break e}f&&n.tests.push(f);if(!t.length||c.name===s)i.push(n),n=u._getToken(n),c.name===s&&(n.combinator=e.Selector.combinators[a[1]]);o=!0}}while(o&&t.length);if(!o||t.length)i=[];return i},_replaceMarkers:function(e){return e=e.replace(/\[/g,"\ue003"),e=e.replace(/\]/g,"\ue004"),e=e.replace(/\(/g,"\ue005"),e=e.replace(/\)/g,"\ue006"),e},_replaceShorthand:function(t){var n=e.Selector.shorthand,r;for(r in n)n.hasOwnProperty(r)&&(t=t.replace(new RegExp(r,"gi"),n[r]));return t},_parseSelector:function(t){var n=e.Selector._replaceSelector(t),t=n.selector;return t=e.Selector._replaceShorthand(t),t=e.Selector._restore("attr",t,n.attrs),t=e.Selector._restore("pseudo",t,n.pseudos),t=e.Selector._replaceMarkers(t),t=e.Selector._restore("esc",t,n.esc),t},_attrFilters:{"class":"className","for":"htmlFor"},getters:{href:function(t,n){return e.DOM.getAttribute(t,n)},id:function(t,n){return e.DOM.getId(t)}}};e.mix(e.Selector,a,!0),e.Selector.getters.src=e.Selector.getters.rel=e.Selector.getters.href,e.Selector.useNative&&e.config.doc.querySelector&&(e.Selector.shorthand["\\.(-?[_a-z]+[-\\w]*)"]="[class~=$1]")},"3.7.3",{requires:["selector-native"]}),YUI.add("selector-css3",function(e,t){e.Selector._reNth=/^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/,e.Selector._getNth=function(t,n,r,i){e.Selector._reNth.test(n);var s=parseInt(RegExp.$1,10),o=RegExp.$2,u=RegExp.$3,a=parseInt(RegExp.$4,10)||0,f=[],l=e.DOM._children(t.parentNode,r),c;u?(s=2,c="+",o="n",a=u==="odd"?1:0):isNaN(s)&&(s=o?1:0);if(s===0)return i&&(a=l.length-a+1),l[a-1]===t?!0:!1;s<0&&(i=!!i,s=Math.abs(s));if(!i){for(var h=a-1,p=l.length;h<p;h+=s)if(h>=0&&l[h]===t)return!0}else for(var h=l.length-a,p=l.length;h>=0;h-=s)if(h<p&&l[h]===t)return!0;return!1},e.mix(e.Selector.pseudos,{root:function(e){return e===e.ownerDocument.documentElement},"nth-child":function(t,n){return e.Selector._getNth(t,n)},"nth-last-child":function(t,n){return e.Selector._getNth(t,n,null,!0)},"nth-of-type":function(t,n){return e.Selector._getNth(t,n,t.tagName)},"nth-last-of-type":function(t,n){return e.Selector._getNth(t,n,t.tagName,!0)},"last-child":function(t){var n=e.DOM._children(t.parentNode);return n[n.length-1]===t},"first-of-type":function(t){return e.DOM._children(t.parentNode,t.tagName)[0]===t},"last-of-type":function(t){var n=e.DOM._children(t.parentNode,t.tagName);return n[n.length-1]===t},"only-child":function(t){var n=e.DOM._children(t.parentNode);return n.length===1&&n[0]===t},"only-of-type":function(t){var n=e.DOM._children(t.parentNode,t.tagName);return n.length===1&&n[0]===t},empty:function(e){return e.childNodes.length===0},not:function(t,n){return!e.Selector.test(t,n)},contains:function(e,t){var n=e.innerText||e.textContent||"";return n.indexOf(t)>-1},checked:function(e){return e.checked===!0||e.selected===!0},enabled:function(e){return e.disabled!==undefined&&!e.disabled},disabled:function(e){return e.disabled}}),e.mix(e.Selector.operators,{"^=":"^{val}","$=":"{val}$","*=":"{val}"}),e.Selector.combinators["~"]={axis:"previousSibling"}},"3.7.3",{requires:["selector-native","selector-css2"]}),YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]}),YUI.add("dump",function(e,t){var n=e.Lang,r="{...}",i="f(){...}",s=", ",o=" => ",u=function(e,t){var u,a,f=[],l=n.type(e);if(!n.isObject(e))return e+"";if(l=="date")return e;if(e.nodeType&&e.tagName)return e.tagName+"#"+e.id;if(e.document&&e.navigator)return"window";if(e.location&&e.body)return"document";if(l=="function")return i;t=n.isNumber(t)?t:3;if(l=="array"){f.push("[");for(u=0,a=e.length;u<a;u+=1)n.isObject(e[u])?f.push(t>0?n.dump(e[u],t-1):r):f.push(e[u]),f.push(s);f.length>1&&f.pop(),f.push("]")}else if(l=="regexp")f.push(e.toString());else{f.push("{");for(u in e)if(e.hasOwnProperty(u))try{f.push(u+o),n.isObject(e[u])?f.push(t>0?n.dump(e[u],t-1):r):f.push(e[u]),f.push(s)}catch(c){f.push("Error: "+c.message)}f.length>1&&f.pop(),f.push("}")}return f.join("")};e.dump=u,n.dump=u},"3.7.3",{requires:["yui-base"]}),YUI.add("transition-timer",function(e,t){var n=e.Transition;e.mix(n.prototype,{_start:function(){n.useNative?this._runNative():this._runTimer()},_runTimer:function(){var t=this;t._initAttrs(),n._running[e.stamp(t)]=t,t._startTime=new Date,n._startTimer()},_endTimer:function(){var t=this;delete n._running[e.stamp(t)],t._startTime=null},_runFrame:function(){var e=new Date-this._startTime;this._runAttrs(e)},_runAttrs:function(t){var r=this,i=r._node,s=r._config,o=e.stamp(i),u=n._nodeAttrs[o],a=n.behaviors,f=!1,l=!1,c,h,p,d,v,m,g,y,b;for(h in u)if((p=u[h])&&p.transition===r){g=p.duration,m=p.delay,v=(t-m)/1e3,y=t,c={type:"propertyEnd",propertyName:h,config:s,elapsedTime:v},d=b in a&&"set"in a[b]?a[b].set:n.DEFAULT_SETTER,f=y>=g,y>g&&(y=g);if(!m||t>=m)d(r,h,p.from,p.to,y-m,g-m,p.easing,p.unit),f&&(delete u[h],r._count--,s[h]&&s[h].on&&s[h].on.end&&s[h].on.end.call(e.one(i),c),!l&&r._count<=0&&(l=!0,r._end(v),r._endTimer()))}},_initAttrs:function(){var t=this,r=n.behaviors,i=e.stamp(t._node),s=n._nodeAttrs[i],o,u,a,f,l,c,h,p,d,v,m;for(c in s)(o=s[c])&&o.transition===t&&(u=o.duration*1e3,a=o.delay*1e3,f=o.easing,l=o.value,c in t._node.style||c in e.DOM.CUSTOM_STYLES?(v=c in r&&"get"in r[c]?r[c].get(t,c):n.DEFAULT_GETTER(t,c),p=n.RE_UNITS.exec(v),h=n.RE_UNITS.exec(l),v=p?p[1]:v,m=h?h[1]:l,d=h?h[2]:p?p[2]:"",!d&&n.RE_DEFAULT_UNIT.test(c)&&(d=n.DEFAULT_UNIT),typeof f=="string"&&(f.indexOf("cubic-bezier")>-1?f=f.substring(13,f.length-1).split(","):n.easings[f]&&(f=n.easings[f])),o.from=Number(v),o.to=Number(m),o.unit=d,o.easing=f,o.duration=u+a,o.delay=a):(delete s[c],t._count--))},destroy:function(){this.detachAll(),this._node=null}},!0),e.mix(e.Transition,{_runtimeAttrs:{},RE_DEFAULT_UNIT:/^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,DEFAULT_UNIT:"px",intervalTime:20,behaviors:{left:{get:function(t,n){return e.DOM._getAttrOffset(t._node,n)}}},DEFAULT_SETTER:function(t,r,i,s,o,u,a,f){i=Number(i),s=Number(s);var l=t._node,c=n.cubicBezier(a,o/u);c=i+c[0]*(s-i);if(l){if(r in l.style||r in e.DOM.CUSTOM_STYLES)f=f||"",e.DOM.setStyle(l,r,c+f)}else t._end()},DEFAULT_GETTER:function(t,n){var r=t._node,i="";if(n in r.style||n in e.DOM.CUSTOM_STYLES)i=e.DOM.getComputedStyle(r,n);return i},_startTimer:function(){n._timer||(n._timer=setInterval(n._runFrame,n.intervalTime))},_stopTimer:function(){clearInterval(n._timer),n._timer=null},_runFrame:function(){var e=!0,t;for(t in n._running)n._running[t]._runFrame&&(e=!1,n._running[t]._runFrame());e&&n._stopTimer()},cubicBezier:function(e,t){var n=0,r=0,i=e[0],s=e[1],o=e[2],u=e[3],a=1,f=0,l=a-3*o+3*i-n,c=3*o-6*i+3*n,h=3*i-3*n,p=n,d=f-3*u+3*s-r,v=3*u-6*s+3*r,m=3*s-3*r,g=r,y=((l*t+c)*t+h)*t+p,b=((d*t+v)*t+m)*t+g;return[y,b]},easings:{ease:[.25,0,1,.25],linear:[0,0,1,1],"ease-in":[.42,0,1,1],"ease-out":[0,0,.58,1],"ease-in-out":[.42,0,.58,1]},_running:{},_timer:null,RE_UNITS:/^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/},!0),n.behaviors.top=n.behaviors.bottom=n.behaviors.right=n.behaviors.left,e.Transition=n},"3.7.3",{requires:["transition"]}),YUI.add("yui",function(e,t){},"3.7.3",{use:["yui","oop","dom","event-custom-base","event-base","pluginhost","node","event-delegate","io-base","json-parse","transition","selector-css3","dom-style-ie","querystring-stringify-simple"]});var Y=YUI().use("*");
diff --git a/js/yui3/slider-base/assets/skins/audio-light/rail-x.png b/js/yui3/slider-base/assets/skins/audio-light/rail-x.png
new file mode 100644
index 000000000..4cd29b45b
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio-light/rail-y.png b/js/yui3/slider-base/assets/skins/audio-light/rail-y.png
new file mode 100644
index 000000000..9bcd2128b
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio-light/slider-base.css b/js/yui3/slider-base/assets/skins/audio-light/slider-base.css
new file mode 100644
index 000000000..d1fec1ba9
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail,.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail{height:35px;background-position:0 7px}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb{height:35px;width:19px}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:13px;left:-5px;width:5px;top:7px}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:13px;right:-5px;width:5px;top:7px}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-3px}.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-43px}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail,.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail{width:35px;background-position:7px 0}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb{width:35px;height:19px}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:13px;top:-5px;height:5px;left:7px}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:13px;bottom:-5px;height:5px;left:7px}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb-image{left:-3px;top:0}.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb-shadow{left:-43px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-audio-light-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/audio-light/slider-skin.css b/js/yui3/slider-base/assets/skins/audio-light/slider-skin.css
new file mode 100644
index 000000000..f583d7613
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/slider-skin.css
@@ -0,0 +1,97 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/audio/thumb-x.png */
+
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+}
+
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail {
+ height: 35px;
+ background-position: 0 7px;
+}
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb {
+ height: 35px;
+ width: 19px;
+}
+
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 13px;
+ left: -5px;
+ width: 5px;
+ top: 7px;
+}
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 13px;
+ right: -5px;
+ width: 5px;
+ top: 7px;
+}
+
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -3px;
+}
+.yui3-skin-audio-light .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -43px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/audio/thumb-y.png */
+
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+}
+
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail {
+ width: 35px;
+ background-position: 7px 0;
+}
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb {
+ width: 35px;
+ height: 19px;
+}
+
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 13px;
+ top: -5px;
+ height: 5px;
+ left: 7px;
+}
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 13px;
+ bottom: -5px;
+ height: 5px;
+ left: 7px;
+}
+
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb-image {
+ left: -3px;
+ top: 0;
+}
+.yui3-skin-audio-light .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -43px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/audio-light/thumb-x.png b/js/yui3/slider-base/assets/skins/audio-light/thumb-x.png
new file mode 100644
index 000000000..f9f69a8ca
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio-light/thumb-y.png b/js/yui3/slider-base/assets/skins/audio-light/thumb-y.png
new file mode 100644
index 000000000..20120d34b
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio-light/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio/rail-x.png b/js/yui3/slider-base/assets/skins/audio/rail-x.png
new file mode 100644
index 000000000..dc37bb249
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio/rail-y.png b/js/yui3/slider-base/assets/skins/audio/rail-y.png
new file mode 100644
index 000000000..7bb0d90e3
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio/slider-base.css b/js/yui3/slider-base/assets/skins/audio/slider-base.css
new file mode 100644
index 000000000..ec50c6fbb
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-audio .yui3-slider-x .yui3-slider-rail,.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-audio .yui3-slider-x .yui3-slider-rail{height:35px;background-position:0 7px}.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb{height:35px;width:19px}.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:13px;left:-5px;width:5px;top:7px}.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:13px;right:-5px;width:5px;top:7px}.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-3px}.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-43px}.yui3-skin-audio .yui3-slider-y .yui3-slider-rail,.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-audio .yui3-slider-y .yui3-slider-rail{width:35px;background-position:7px 0}.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb{width:35px;height:19px}.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:13px;top:-5px;height:5px;left:7px}.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:13px;bottom:-5px;height:5px;left:7px}.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb-image{left:-3px;top:0}.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb-shadow{left:-43px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-audio-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/audio/slider-skin.css b/js/yui3/slider-base/assets/skins/audio/slider-skin.css
new file mode 100644
index 000000000..9408bf78a
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/slider-skin.css
@@ -0,0 +1,97 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/audio/thumb-x.png */
+
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+}
+
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail {
+ height: 35px;
+ background-position: 0 7px;
+}
+.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb {
+ height: 35px;
+ width: 19px;
+}
+
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 13px;
+ left: -5px;
+ width: 5px;
+ top: 7px;
+}
+.yui3-skin-audio .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 13px;
+ right: -5px;
+ width: 5px;
+ top: 7px;
+}
+
+.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -3px;
+}
+.yui3-skin-audio .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -43px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/audio/thumb-y.png */
+
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+}
+
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail {
+ width: 35px;
+ background-position: 7px 0;
+}
+.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb {
+ width: 35px;
+ height: 19px;
+}
+
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 13px;
+ top: -5px;
+ height: 5px;
+ left: 7px;
+}
+.yui3-skin-audio .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 13px;
+ bottom: -5px;
+ height: 5px;
+ left: 7px;
+}
+
+.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb-image {
+ left: -3px;
+ top: 0;
+}
+.yui3-skin-audio .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -43px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/audio/thumb-x.png b/js/yui3/slider-base/assets/skins/audio/thumb-x.png
new file mode 100644
index 000000000..e0fbfb2a3
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/audio/thumb-y.png b/js/yui3/slider-base/assets/skins/audio/thumb-y.png
new file mode 100644
index 000000000..38dfc3f00
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/audio/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-dots.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-dots.png
new file mode 100644
index 000000000..453fb64f3
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-dots.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-lines.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-lines.png
new file mode 100644
index 000000000..8a3c981bb
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-x.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x.png
new file mode 100644
index 000000000..f1aa290ee
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-dots.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-dots.png
new file mode 100644
index 000000000..0555b19d6
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-dots.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-lines.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-lines.png
new file mode 100644
index 000000000..178aa85e1
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/rail-y.png b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y.png
new file mode 100644
index 000000000..a47997f25
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/slider-base.css b/js/yui3/slider-base/assets/skins/capsule-dark/slider-base.css
new file mode 100644
index 000000000..2cfd2f831
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail,.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail{height:25px}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb{height:30px;width:14px}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail,.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail{width:25px}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb{width:30px;height:14px}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-capsule-dark-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/slider-skin.css b/js/yui3/slider-base/assets/skins/capsule-dark/slider-skin.css
new file mode 100644
index 000000000..d2c659fa5
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/slider-skin.css
@@ -0,0 +1,97 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/capsule-dark/thumb-x.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/capsule-dark/thumb-x-line.png */
+
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+ /* alternate: rail-x-dots.png */
+ /* alternate: rail-x-lines.png */
+}
+
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail {
+ height: 25px;
+}
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb {
+ height: 30px;
+ width: 14px;
+}
+
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -10px;
+}
+.yui3-skin-capsule-dark .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -50px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/capsule-dark/thumb-y.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/capsule-dark/thumb-y-line.png */
+
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+ /* alternate: rail-y-dots.png */
+ /* alternate: rail-y-lines.png */
+}
+
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail {
+ width: 25px;
+}
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb {
+ width: 30px;
+ height: 14px;
+}
+
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb-image {
+ left: -10px;
+ top: 0;
+}
+.yui3-skin-capsule-dark .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -50px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x-line.png b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x-line.png
new file mode 100644
index 000000000..bfdbe0db8
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x-line.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x.png b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x.png
new file mode 100644
index 000000000..abed02533
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y-line.png b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y-line.png
new file mode 100644
index 000000000..037dca38d
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y-line.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y.png b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y.png
new file mode 100644
index 000000000..e968ed42e
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule-dark/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-x-dots.png b/js/yui3/slider-base/assets/skins/capsule/rail-x-dots.png
new file mode 100644
index 000000000..b3f65d499
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-x-dots.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-x-lines.png b/js/yui3/slider-base/assets/skins/capsule/rail-x-lines.png
new file mode 100644
index 000000000..26374dfad
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-x.png b/js/yui3/slider-base/assets/skins/capsule/rail-x.png
new file mode 100644
index 000000000..f257ec000
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-y-dots.png b/js/yui3/slider-base/assets/skins/capsule/rail-y-dots.png
new file mode 100644
index 000000000..798c2ce3c
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-y-dots.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-y-lines.png b/js/yui3/slider-base/assets/skins/capsule/rail-y-lines.png
new file mode 100644
index 000000000..798c2ce3c
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/rail-y.png b/js/yui3/slider-base/assets/skins/capsule/rail-y.png
new file mode 100644
index 000000000..d20d3c3e9
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/slider-base.css b/js/yui3/slider-base/assets/skins/capsule/slider-base.css
new file mode 100644
index 000000000..46563acf7
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail,.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x;background-repeat:repeat-x}.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail{height:25px}.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb{height:30px;width:14px}.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail,.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y;background-repeat:repeat-y}.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail{width:25px}.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb{width:30px;height:14px}.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-capsule-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/capsule/slider-skin.css b/js/yui3/slider-base/assets/skins/capsule/slider-skin.css
new file mode 100644
index 000000000..380b1f2e3
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/slider-skin.css
@@ -0,0 +1,99 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/capsule/thumb-x.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/capsule/thumb-x-line.png */
+
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+ background-repeat: repeat-x;
+ /* alternate: rail-x-dots.png */
+ /* alternate: rail-x-lines.png */
+}
+
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail {
+ height: 25px;
+}
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb {
+ height: 30px;
+ width: 14px;
+}
+
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -10px;
+}
+.yui3-skin-capsule .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -50px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/capsule/thumb-y.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/capsule/thumb-y-line.png */
+
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+ background-repeat: repeat-y;
+ /* alternate: rail-y-dots.png */
+ /* alternate: rail-y-lines.png */
+}
+
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail {
+ width: 25px;
+}
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb {
+ width: 30px;
+ height: 14px;
+}
+
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb-image {
+ left: -10px;
+ top: 0;
+}
+.yui3-skin-capsule .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -50px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/capsule/thumb-x-line.png b/js/yui3/slider-base/assets/skins/capsule/thumb-x-line.png
new file mode 100644
index 000000000..849a4548c
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/thumb-x-line.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/thumb-x.png b/js/yui3/slider-base/assets/skins/capsule/thumb-x.png
new file mode 100644
index 000000000..09baa964b
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/thumb-y-line.png b/js/yui3/slider-base/assets/skins/capsule/thumb-y-line.png
new file mode 100644
index 000000000..153c65b1c
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/thumb-y-line.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/thumb-y-lines.png b/js/yui3/slider-base/assets/skins/capsule/thumb-y-lines.png
new file mode 100644
index 000000000..4421d7027
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/thumb-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/capsule/thumb-y.png b/js/yui3/slider-base/assets/skins/capsule/thumb-y.png
new file mode 100644
index 000000000..4040ee352
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/capsule/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/rail-x-lines.png b/js/yui3/slider-base/assets/skins/night/rail-x-lines.png
new file mode 100644
index 000000000..4e5a44070
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/rail-x.png b/js/yui3/slider-base/assets/skins/night/rail-x.png
new file mode 100644
index 000000000..7079de67f
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/rail-y-lines.png b/js/yui3/slider-base/assets/skins/night/rail-y-lines.png
new file mode 100644
index 000000000..af2bc2480
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/rail-y.png b/js/yui3/slider-base/assets/skins/night/rail-y.png
new file mode 100644
index 000000000..bc096bc77
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/slider-base.css b/js/yui3/slider-base/assets/skins/night/slider-base.css
new file mode 100644
index 000000000..dace56f40
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-night .yui3-slider-x .yui3-slider-rail,.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-night .yui3-slider-x .yui3-slider-rail{height:25px}.yui3-skin-night .yui3-slider-x .yui3-slider-thumb{height:26px;width:21px}.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-5px;width:5px}.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-5px;width:5px}.yui3-skin-night .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-night .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-night .yui3-slider-y .yui3-slider-rail,.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-night .yui3-slider-y .yui3-slider-rail{width:25px}.yui3-skin-night .yui3-slider-y .yui3-slider-thumb{width:26px;height:21px}.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-5px;height:5px}.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-5px;height:5px}.yui3-skin-night .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-night .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-night-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/night/slider-skin.css b/js/yui3/slider-base/assets/skins/night/slider-skin.css
new file mode 100644
index 000000000..1c79f40ea
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/slider-skin.css
@@ -0,0 +1,93 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam-dark/thumb-x.png */
+
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+ /* alternate: rail-x-lines.png */
+}
+
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail {
+ height: 26px;
+}
+.yui3-skin-night .yui3-slider-x .yui3-slider-thumb {
+ height: 26px;
+ width: 21px;
+}
+
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-night .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-night .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -10px;
+}
+.yui3-skin-night .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -50px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam-dark/thumb-y.png */
+
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+ /* alternate: rail-y-lines.png */
+}
+
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail {
+ width: 26px;
+}
+.yui3-skin-night .yui3-slider-y .yui3-slider-thumb {
+ width: 26px;
+ height: 15px;
+}
+
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-night .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-night .yui3-slider-y .yui3-slider-thumb-image {
+ left: -10px;
+ top: 0;
+}
+.yui3-skin-night .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -50px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/night/thumb-x.png b/js/yui3/slider-base/assets/skins/night/thumb-x.png
new file mode 100644
index 000000000..2045257c2
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/night/thumb-y.png b/js/yui3/slider-base/assets/skins/night/thumb-y.png
new file mode 100644
index 000000000..5ea57f08e
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/night/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/rail-x.png b/js/yui3/slider-base/assets/skins/round-dark/rail-x.png
new file mode 100644
index 000000000..ce0ee5024
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/rail-y.png b/js/yui3/slider-base/assets/skins/round-dark/rail-y.png
new file mode 100644
index 000000000..7fedc219c
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/slider-base.css b/js/yui3/slider-base/assets/skins/round-dark/slider-base.css
new file mode 100644
index 000000000..76031e841
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail,.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail{height:25px;background-position:0 3px}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb{height:26px;width:24px}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -17px;height:20px;left:-2px;width:5px}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -37px;height:20px;right:-2px;width:5px}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-7px}.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-47px}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail,.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail{width:25px;background-position:3px 0}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb{width:26px;height:24px}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-17px 0;width:20px;top:-2px;height:5px}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-37px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb-image{top:0;left:-7px}.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb-shadow{top:0;left:-47px;opacity:.15;filter:alpha(opacity=15)}#yui3-css-stamp.skin-round-dark-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/round-dark/slider-skin.css b/js/yui3/slider-base/assets/skins/round-dark/slider-skin.css
new file mode 100644
index 000000000..dada70d43
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/slider-skin.css
@@ -0,0 +1,95 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/round-dark/thumb-x.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/round-dark/thumb-x-grip.png */
+
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+}
+
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail {
+ height: 25px;
+ background-position: 0 3px;
+}
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb {
+ height: 26px;
+ width: 24px;
+}
+
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -17px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -37px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -7px;
+}
+.yui3-skin-round-dark .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -47px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/round-dark/thumb-y.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/round-dark/thumb-y-grip.png */
+
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+}
+
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail {
+ width: 25px;
+ background-position: 3px 0;
+}
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb {
+ width: 26px;
+ height: 24px;
+}
+
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -17px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -37px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb-image {
+ top: 0;
+ left: -7px;
+}
+.yui3-skin-round-dark .yui3-slider-y .yui3-slider-thumb-shadow {
+ top: 0;
+ left: -47px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+}
diff --git a/js/yui3/slider-base/assets/skins/round-dark/thumb-x-grip.png b/js/yui3/slider-base/assets/skins/round-dark/thumb-x-grip.png
new file mode 100644
index 000000000..858964b82
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/thumb-x-grip.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/thumb-x.png b/js/yui3/slider-base/assets/skins/round-dark/thumb-x.png
new file mode 100644
index 000000000..df181708f
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/thumb-y-grip.png b/js/yui3/slider-base/assets/skins/round-dark/thumb-y-grip.png
new file mode 100644
index 000000000..2773a4a9f
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/thumb-y-grip.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round-dark/thumb-y.png b/js/yui3/slider-base/assets/skins/round-dark/thumb-y.png
new file mode 100644
index 000000000..8ed649cc7
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round-dark/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/rail-x.png b/js/yui3/slider-base/assets/skins/round/rail-x.png
new file mode 100644
index 000000000..62a4e92d6
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/rail-y.png b/js/yui3/slider-base/assets/skins/round/rail-y.png
new file mode 100644
index 000000000..86f0b8ca2
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/slider-base.css b/js/yui3/slider-base/assets/skins/round/slider-base.css
new file mode 100644
index 000000000..df24a3bd1
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-round .yui3-slider-x .yui3-slider-rail,.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-round .yui3-slider-x .yui3-slider-rail{height:25px;background-position:0 3px}.yui3-skin-round .yui3-slider-x .yui3-slider-thumb{height:26px;width:24px}.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -17px;height:20px;left:-2px;width:5px}.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -37px;height:20px;right:-2px;width:5px}.yui3-skin-round .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-7px}.yui3-skin-round .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-47px}.yui3-skin-round .yui3-slider-y .yui3-slider-rail,.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-round .yui3-slider-y .yui3-slider-rail{width:25px;background-position:3px 0}.yui3-skin-round .yui3-slider-y .yui3-slider-thumb{width:26px;height:24px}.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-17px 0;width:20px;top:-2px;height:5px}.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-37px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-round .yui3-slider-y .yui3-slider-thumb-image{top:0;left:-8px}.yui3-skin-round .yui3-slider-y .yui3-slider-thumb-shadow{top:0;left:-48px;opacity:.15;filter:alpha(opacity=15)}#yui3-css-stamp.skin-round-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/round/slider-skin.css b/js/yui3/slider-base/assets/skins/round/slider-skin.css
new file mode 100644
index 000000000..6801b049e
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/slider-skin.css
@@ -0,0 +1,95 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/round/thumb-x.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/round/thumb-x-grip.png */
+
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+}
+
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail {
+ height: 25px;
+ background-position: 0 3px;
+}
+.yui3-skin-round .yui3-slider-x .yui3-slider-thumb {
+ height: 26px;
+ width: 24px;
+}
+
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -17px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-round .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -37px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-round .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -7px;
+}
+.yui3-skin-round .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -47px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/round/thumb-y.png */
+/* Alternate thumbUrl /build/slider-base/assets/skins/round/thumb-y-grip.png */
+
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+}
+
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail {
+ width: 25px;
+ background-position: 3px 0;
+}
+.yui3-skin-round .yui3-slider-y .yui3-slider-thumb {
+ width: 26px;
+ height: 24px;
+}
+
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -17px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-round .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -37px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-round .yui3-slider-y .yui3-slider-thumb-image {
+ top: 0;
+ left: -8px;
+}
+.yui3-skin-round .yui3-slider-y .yui3-slider-thumb-shadow {
+ top: 0;
+ left: -48px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+}
diff --git a/js/yui3/slider-base/assets/skins/round/thumb-x-grip.png b/js/yui3/slider-base/assets/skins/round/thumb-x-grip.png
new file mode 100644
index 000000000..b80b8ac79
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/thumb-x-grip.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/thumb-x.png b/js/yui3/slider-base/assets/skins/round/thumb-x.png
new file mode 100644
index 000000000..22ac2a5b9
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/thumb-y-grip.png b/js/yui3/slider-base/assets/skins/round/thumb-y-grip.png
new file mode 100644
index 000000000..1bf7ff3e4
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/thumb-y-grip.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/round/thumb-y.png b/js/yui3/slider-base/assets/skins/round/thumb-y.png
new file mode 100644
index 000000000..a8a0c6202
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/round/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/rail-x-lines.png b/js/yui3/slider-base/assets/skins/sam-dark/rail-x-lines.png
new file mode 100644
index 000000000..39ac404cc
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/rail-x.png b/js/yui3/slider-base/assets/skins/sam-dark/rail-x.png
new file mode 100644
index 000000000..bdbc07cdd
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/rail-y-lines.png b/js/yui3/slider-base/assets/skins/sam-dark/rail-y-lines.png
new file mode 100644
index 000000000..0553faa9a
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/rail-y.png b/js/yui3/slider-base/assets/skins/sam-dark/rail-y.png
new file mode 100644
index 000000000..a2913427e
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/slider-base.css b/js/yui3/slider-base/assets/skins/sam-dark/slider-base.css
new file mode 100644
index 000000000..cbde8ccfb
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail,.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail{height:26px}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb{height:26px;width:15px}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail,.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail{width:26px}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb{width:26px;height:15px}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-sam-dark-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/slider-skin.css b/js/yui3/slider-base/assets/skins/sam-dark/slider-skin.css
new file mode 100644
index 000000000..a3be34cc3
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/slider-skin.css
@@ -0,0 +1,93 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam-dark/thumb-x.png */
+
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+ /* alternate: rail-x-lines.png */
+}
+
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail {
+ height: 26px;
+}
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb {
+ height: 26px;
+ width: 15px;
+}
+
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -10px;
+}
+.yui3-skin-sam-dark .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -50px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam-dark/thumb-y.png */
+
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+ /* alternate: rail-y-lines.png */
+}
+
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail {
+ width: 26px;
+}
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb {
+ width: 26px;
+ height: 15px;
+}
+
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb-image {
+ left: -10px;
+ top: 0;
+}
+.yui3-skin-sam-dark .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -50px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/thumb-x.png b/js/yui3/slider-base/assets/skins/sam-dark/thumb-x.png
new file mode 100644
index 000000000..3526ffc15
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam-dark/thumb-y.png b/js/yui3/slider-base/assets/skins/sam-dark/thumb-y.png
new file mode 100644
index 000000000..9aad18b57
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam-dark/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/rail-x-lines.png b/js/yui3/slider-base/assets/skins/sam/rail-x-lines.png
new file mode 100644
index 000000000..45c84288f
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/rail-x-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/rail-x.png b/js/yui3/slider-base/assets/skins/sam/rail-x.png
new file mode 100644
index 000000000..b99e1049e
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/rail-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/rail-y-lines.png b/js/yui3/slider-base/assets/skins/sam/rail-y-lines.png
new file mode 100644
index 000000000..841c97088
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/rail-y-lines.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/rail-y.png b/js/yui3/slider-base/assets/skins/sam/rail-y.png
new file mode 100644
index 000000000..2bec78ab6
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/rail-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/slider-base.css b/js/yui3/slider-base/assets/skins/sam/slider-base.css
new file mode 100644
index 000000000..0bca65481
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/slider-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,.yui3-slider-rail{display:-moz-inline-stack;display:inline-block;*display:inline;zoom:1;vertical-align:middle}.yui3-slider-content{position:relative;display:block}.yui3-slider-rail{position:relative}.yui3-slider-rail-cap-top,.yui3-slider-rail-cap-left,.yui3-slider-rail-cap-bottom,.yui3-slider-rail-cap-right,.yui3-slider-thumb,.yui3-slider-thumb-image,.yui3-slider-thumb-shadow{position:absolute}.yui3-slider-thumb{overflow:hidden}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left,.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-image:url(rail-x.png);background-repeat:repeat-x}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail{height:26px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb{height:26px;width:15px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left{background-position:0 -20px;height:20px;left:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right{background-position:0 -40px;height:20px;right:-2px;width:5px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-image{left:0;top:-10px}.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-shadow{left:0;opacity:.15;filter:alpha(opacity=15);top:-50px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top,.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-image:url(rail-y.png);background-repeat:repeat-y}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail{width:26px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb{width:26px;height:15px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top{background-position:-20px 0;width:20px;top:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom{background-position:-40px 0;width:20px;bottom:-2px;height:5px}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-image{left:-10px;top:0}.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-shadow{left:-50px;opacity:.15;filter:alpha(opacity=15);top:0}#yui3-css-stamp.skin-sam-slider-base{display:none}
diff --git a/js/yui3/slider-base/assets/skins/sam/slider-skin.css b/js/yui3/slider-base/assets/skins/sam/slider-skin.css
new file mode 100644
index 000000000..8414d6bb4
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/slider-skin.css
@@ -0,0 +1,93 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* Horizontal Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam/thumb-x.png */
+
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail,
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left,
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-image: url(rail-x.png);
+ background-repeat: repeat-x;
+ /* alternate: rail-x-lines.png */
+}
+
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail {
+ height: 26px;
+}
+.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb {
+ height: 26px;
+ width: 15px;
+}
+
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-left {
+ background-position: 0 -20px;
+ height: 20px;
+ left: -2px;
+ width: 5px;
+}
+.yui3-skin-sam .yui3-slider-x .yui3-slider-rail-cap-right {
+ background-position: 0 -40px;
+ height: 20px;
+ right: -2px;
+ width: 5px;
+}
+
+.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-image {
+ left: 0;
+ top: -10px;
+}
+.yui3-skin-sam .yui3-slider-x .yui3-slider-thumb-shadow {
+ left: 0;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: -50px;
+}
+
+/* Vertical Slider */
+
+/* Use thumbUrl /build/slider-base/assets/skins/sam/thumb-y.png */
+
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail,
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top,
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-image: url(rail-y.png);
+ background-repeat: repeat-y;
+ /* alternate: rail-y-lines.png */
+}
+
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail {
+ width: 26px;
+}
+.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb {
+ width: 26px;
+ height: 15px;
+}
+
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-top {
+ background-position: -20px 0;
+ width: 20px;
+ top: -2px;
+ height: 5px;
+}
+.yui3-skin-sam .yui3-slider-y .yui3-slider-rail-cap-bottom {
+ background-position: -40px 0;
+ width: 20px;
+ bottom: -2px;
+ height: 5px;
+}
+
+.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-image {
+ left: -10px;
+ top: 0;
+}
+.yui3-skin-sam .yui3-slider-y .yui3-slider-thumb-shadow {
+ left: -50px;
+ opacity: 0.15;
+ filter: alpha(opacity=15);
+ top: 0;
+}
diff --git a/js/yui3/slider-base/assets/skins/sam/thumb-x.png b/js/yui3/slider-base/assets/skins/sam/thumb-x.png
new file mode 100644
index 000000000..4d4bcbd48
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/thumb-x.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/skins/sam/thumb-y.png b/js/yui3/slider-base/assets/skins/sam/thumb-y.png
new file mode 100644
index 000000000..0b17a0ed2
--- /dev/null
+++ b/js/yui3/slider-base/assets/skins/sam/thumb-y.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/slider-base-core.css b/js/yui3/slider-base/assets/slider-base-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/slider-base/assets/slider-base-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/slider-base/assets/slider-core.css b/js/yui3/slider-base/assets/slider-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/slider-base/assets/slider-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/slider-base/assets/thumb-x-oblong-dark.png b/js/yui3/slider-base/assets/thumb-x-oblong-dark.png
new file mode 100644
index 000000000..bc0aa14ce
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-x-oblong-dark.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-x-oblong.png b/js/yui3/slider-base/assets/thumb-x-oblong.png
new file mode 100644
index 000000000..670ba1ea1
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-x-oblong.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-x-oblong2-dark.png b/js/yui3/slider-base/assets/thumb-x-oblong2-dark.png
new file mode 100644
index 000000000..20f126029
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-x-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-x-oblong2.png b/js/yui3/slider-base/assets/thumb-x-oblong2.png
new file mode 100644
index 000000000..76e34e60a
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-x-oblong2.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-y-oblong-dark.png b/js/yui3/slider-base/assets/thumb-y-oblong-dark.png
new file mode 100644
index 000000000..a0eed7087
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-y-oblong-dark.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-y-oblong.png b/js/yui3/slider-base/assets/thumb-y-oblong.png
new file mode 100644
index 000000000..e63c8d7d8
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-y-oblong.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-y-oblong2-dark.png b/js/yui3/slider-base/assets/thumb-y-oblong2-dark.png
new file mode 100644
index 000000000..e91ffb7b3
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-y-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/slider-base/assets/thumb-y-oblong2.png b/js/yui3/slider-base/assets/thumb-y-oblong2.png
new file mode 100644
index 000000000..89a466727
--- /dev/null
+++ b/js/yui3/slider-base/assets/thumb-y-oblong2.png
Binary files differ
diff --git a/js/yui3/slider-base/slider-base-min.js b/js/yui3/slider-base/slider-base-min.js
new file mode 100644
index 000000000..2b69eea6c
--- /dev/null
+++ b/js/yui3/slider-base/slider-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("slider-base",function(e,t){function r(){r.superclass.constructor.apply(this,arguments)}var n=e.Attribute.INVALID_VALUE;e.SliderBase=e.extend(r,e.Widget,{initializer:function(){this.axis=this.get("axis"),this._key={dim:this.axis==="y"?"height":"width",minEdge:this.axis==="y"?"top":"left",maxEdge:this.axis==="y"?"bottom":"right",xyIndex:this.axis==="y"?1:0},this.publish("thumbMove",{defaultFn:this._defThumbMoveFn,queuable:!0})},renderUI:function(){var e=this.get("contentBox");this.rail=this.renderRail(),this._uiSetRailLength(this.get("length")),this.thumb=this.renderThumb(),this.rail.appendChild(this.thumb),e.appendChild(this.rail),e.addClass(this.getClassName(this.axis))},renderRail:function(){var t=this.getClassName("rail","cap",this._key.minEdge),n=this.getClassName("rail","cap",this._key.maxEdge);return e.Node.create(e.Lang.sub(this.RAIL_TEMPLATE,{railClass:this.getClassName("rail"),railMinCapClass:t,railMaxCapClass:n}))},_uiSetRailLength:function(e){this.rail.setStyle(this._key.dim,e)},renderThumb:function(){this._initThumbUrl();var t=this.get("thumbUrl");return e.Node.create(e.Lang.sub(this.THUMB_TEMPLATE,{thumbClass:this.getClassName("thumb"),thumbShadowClass:this.getClassName("thumb","shadow"),thumbImageClass:this.getClassName("thumb","image"),thumbShadowUrl:t,thumbImageUrl:t,thumbAriaLabelId:this.getClassName("label",e.guid())}))},_onThumbClick:function(e){this.thumb.focus()},bindUI:function(){var t=this.get("boundingBox"),n=e.UA.opera?"press:":"down:",r=n+"38,40,33,34,35,36",i=n+"37,39",s=n+"37+meta,39+meta";t.on("key",this._onDirectionKey,r,this),t.on("key",this._onLeftRightKey,i,this),t.on("key",this._onLeftRightKeyMeta,s,this),this.thumb.on("click",this._onThumbClick,this),this._bindThumbDD(),this._bindValueLogic(),this.after("disabledChange",this._afterDisabledChange),this.after("lengthChange",this._afterLengthChange)},_incrMinor:function(){this.set("value",this.get("value")+this.get("minorStep"))},_decrMinor:function(){this.set("value",this.get("value")-this.get("minorStep"))},_incrMajor:function(){this.set("value",this.get("value")+this.get("majorStep"))},_decrMajor:function(){this.set("value",this.get("value")-this.get("majorStep"))},_setToMin:function(e){this.set("value",this.get("min"))},_setToMax:function(e){this.set("value",this.get("max"))},_onDirectionKey:function(e){e.preventDefault();if(this.get("disabled")===!1)switch(e.charCode){case 38:this._incrMinor();break;case 40:this._decrMinor();break;case 36:this._setToMin();break;case 35:this._setToMax();break;case 33:this._incrMajor();break;case 34:this._decrMajor()}},_onLeftRightKey:function(e){e.preventDefault();if(this.get("disabled")===!1)switch(e.charCode){case 37:this._decrMinor();break;case 39:this._incrMinor()}},_onLeftRightKeyMeta:function(e){e.preventDefault();if(this.get("disabled")===!1)switch(e.charCode){case 37:this._setToMin();break;case 39:this._setToMax()}},_bindThumbDD:function(){var t={constrain:this.rail};t["stick"+this.axis.toUpperCase()]=!0,this._dd=new e.DD.Drag({node:this.thumb,bubble:!1,on:{"drag:start":e.bind(this._onDragStart,this)},after:{"drag:drag":e.bind(this._afterDrag,this),"drag:end":e.bind(this._afterDragEnd,this)}}),this._dd.plug(e.Plugin.DDConstrained,t)},_bindValueLogic:function(){},_uiMoveThumb:function(e,t){this.thumb&&(this.thumb.setStyle(this._key.minEdge,e+"px"),t||(t={}),t.offset=e,this.fire("thumbMove",t))},_onDragStart:function(e){this.fire("slideStart",{ddEvent:e,originEvent:e})},_afterDrag:function(e){var t=e.info.xy[this._key.xyIndex],n=e.target.con._regionCache[this._key.minEdge];this.fire("thumbMove",{offset:t-n,ddEvent:e,originEvent:e})},_afterDragEnd:function(e){this.fire("slideEnd",{ddEvent:e,originEvent:e})},_afterDisabledChange:function(e){this._dd.set("lock",e.newVal)},_afterLengthChange:function(e){this.get("rendered")&&(this._uiSetRailLength(e.newVal),this.syncUI())},syncUI:function(){this._dd.con.resetCache(),this._syncThumbPosition(),this.thumb.set("aria-valuemin",this.get("min")),this.thumb.set("aria-valuemax",this.get("max")),this._dd.set("lock",this.get("disabled"))},_syncThumbPosition:function(){},_setAxis:function(e){return e=(e+"").toLowerCase(),e==="x"||e==="y"?e:n},_setLength:function(e){e=(e+"").toLowerCase();var t=parseFloat(e,10),r=e.replace(/[\d\.\-]/g,"")||this.DEF_UNIT;return t>0?t+r:n},_initThumbUrl:function(){if(!this.get("thumbUrl")){var t=this.getSkinName()||"sam",n=e.config.base;n.indexOf("http://yui.yahooapis.com/combo")===0&&(n="http://yui.yahooapis.com/"+e.version+"/build/"),this.set("thumbUrl",n+"slider-base/assets/skins/"+t+"/thumb-"+this.axis+".png")}},BOUNDING_TEMPLATE:"<span></span>",CONTENT_TEMPLATE:"<span></span>",RAIL_TEMPLATE:'<span class="{railClass}"><span class="{railMinCapClass}"></span><span class="{railMaxCapClass}"></span></span>',THUMB_TEMPLATE:'<span class="{thumbClass}" aria-labelledby="{thumbAriaLabelId}" aria-valuetext="" aria-valuemax="" aria-valuemin="" aria-valuenow="" role="slider" tabindex="0"><img src="{thumbShadowUrl}" alt="Slider thumb shadow" class="{thumbShadowClass}"><img src="{thumbImageUrl}" alt="Slider thumb" class="{thumbImageClass}"></span>'},{NAME:"sliderBase",ATTRS:{axis:{value:"x",writeOnce:!0,setter:"_setAxis",lazyAdd:!1},length:{value:"150px",setter:"_setLength"},thumbUrl:{value:null,validator:e.Lang.isString}}})},"3.7.3",{requires:["widget","dd-constrain","event-key"],skinnable:!0});
diff --git a/js/yui3/slider-value-range/assets/slider-base-core.css b/js/yui3/slider-value-range/assets/slider-base-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/slider-base-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/slider-value-range/assets/slider-core.css b/js/yui3/slider-value-range/assets/slider-core.css
new file mode 100644
index 000000000..905d4a34d
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/slider-core.css
@@ -0,0 +1,37 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-slider,
+.yui3-slider-rail {
+ /* xbrowser inline-block styles */
+ display: -moz-inline-stack; /* FF2 */
+ display: inline-block;
+ *display: inline; /* IE 7- (with zoom) */
+ zoom: 1;
+ vertical-align: middle;
+}
+
+.yui3-slider-content {
+ position: relative;
+ display: block;
+}
+.yui3-slider-rail {
+ position: relative;
+}
+
+.yui3-slider-rail-cap-top,
+.yui3-slider-rail-cap-left,
+.yui3-slider-rail-cap-bottom,
+.yui3-slider-rail-cap-right,
+.yui3-slider-thumb,
+.yui3-slider-thumb-image,
+.yui3-slider-thumb-shadow {
+ position: absolute;
+}
+
+.yui3-slider-thumb {
+ overflow: hidden;
+}
diff --git a/js/yui3/slider-value-range/assets/thumb-x-oblong-dark.png b/js/yui3/slider-value-range/assets/thumb-x-oblong-dark.png
new file mode 100644
index 000000000..bc0aa14ce
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-x-oblong-dark.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-x-oblong.png b/js/yui3/slider-value-range/assets/thumb-x-oblong.png
new file mode 100644
index 000000000..670ba1ea1
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-x-oblong.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-x-oblong2-dark.png b/js/yui3/slider-value-range/assets/thumb-x-oblong2-dark.png
new file mode 100644
index 000000000..20f126029
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-x-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-x-oblong2.png b/js/yui3/slider-value-range/assets/thumb-x-oblong2.png
new file mode 100644
index 000000000..76e34e60a
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-x-oblong2.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-y-oblong-dark.png b/js/yui3/slider-value-range/assets/thumb-y-oblong-dark.png
new file mode 100644
index 000000000..a0eed7087
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-y-oblong-dark.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-y-oblong.png b/js/yui3/slider-value-range/assets/thumb-y-oblong.png
new file mode 100644
index 000000000..e63c8d7d8
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-y-oblong.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-y-oblong2-dark.png b/js/yui3/slider-value-range/assets/thumb-y-oblong2-dark.png
new file mode 100644
index 000000000..e91ffb7b3
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-y-oblong2-dark.png
Binary files differ
diff --git a/js/yui3/slider-value-range/assets/thumb-y-oblong2.png b/js/yui3/slider-value-range/assets/thumb-y-oblong2.png
new file mode 100644
index 000000000..89a466727
--- /dev/null
+++ b/js/yui3/slider-value-range/assets/thumb-y-oblong2.png
Binary files differ
diff --git a/js/yui3/slider-value-range/slider-value-range-min.js b/js/yui3/slider-value-range/slider-value-range-min.js
new file mode 100644
index 000000000..b0acdd765
--- /dev/null
+++ b/js/yui3/slider-value-range/slider-value-range-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("slider-value-range",function(e,t){function o(){this._initSliderValueRange()}var n="min",r="max",i="value",s=Math.round;e.SliderValueRange=e.mix(o,{prototype:{_factor:1,_initSliderValueRange:function(){},_bindValueLogic:function(){this.after({minChange:this._afterMinChange,maxChange:this._afterMaxChange,valueChange:this._afterValueChange})},_syncThumbPosition:function(){this._calculateFactor(),this._setPosition(this.get(i))},_calculateFactor:function(){var e=this.get("length"),t=this.thumb.getStyle(this._key.dim),i=this.get(n),s=this.get(r);e=parseFloat(e)||150,t=parseFloat(t)||15,this._factor=(s-i)/(e-t)},_defThumbMoveFn:function(e){e.source!=="set"&&this.set(i,this._offsetToValue(e.offset))},_offsetToValue:function(e){var t=s(e*this._factor)+this.get(n);return s(this._nearestValue(t))},_valueToOffset:function(e){var t=s((e-this.get(n))/this._factor);return t},getValue:function(){return this.get(i)},setValue:function(e){return this.set(i,e)},_afterMinChange:function(e){this._verifyValue(),this._syncThumbPosition()},_afterMaxChange:function(e){this._verifyValue(),this._syncThumbPosition()},_verifyValue:function(){var e=this.get(i),t=this._nearestValue(e);e!==t&&this.set(i,t)},_afterValueChange:function(e){var t=e.newVal;this._setPosition(t,{source:"set"}),this.thumb.set("aria-valuenow",t),this.thumb.set("aria-valuetext",t)},_setPosition:function(e,t){this._uiMoveThumb(this._valueToOffset(e),t)},_validateNewMin:function(t){return e.Lang.isNumber(t)},_validateNewMax:function(t){return e.Lang.isNumber(t)},_setNewValue:function(e){return s(this._nearestValue(e))},_nearestValue:function(e){var t=this.get(n),i=this.get(r),s;return s=i>t?i:t,t=i>t?t:i,i=s,e<t?t:e>i?i:e}},ATTRS:{min:{value:0,validator:"_validateNewMin"},max:{value:100,validator:"_validateNewMax"},minorStep:{value:1},majorStep:{value:10},value:{value:0,setter:"_setNewValue"}}},!0)},"3.7.3",{requires:["slider-base"]});
diff --git a/js/yui3/sortable-scroll/sortable-scroll-min.js b/js/yui3/sortable-scroll/sortable-scroll-min.js
new file mode 100644
index 000000000..d9080f622
--- /dev/null
+++ b/js/yui3/sortable-scroll/sortable-scroll-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("sortable-scroll",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)};e.extend(n,e.Base,{initializer:function(){var t=this.get("host");t.plug(e.Plugin.DDNodeScroll,{node:t.get("container")}),t.delegate.on("drop:over",function(t){this.dd.nodescroll&&t.drag.nodescroll&&t.drag.nodescroll.set("parentScroll",e.one(this.get("container")))})}},{ATTRS:{host:{value:""}},NAME:"SortScroll",NS:"scroll"}),e.namespace("Y.Plugin"),e.Plugin.SortableScroll=n},"3.7.3",{requires:["dd-scroll","sortable"]});
diff --git a/js/yui3/sortable/sortable-min.js b/js/yui3/sortable/sortable-min.js
new file mode 100644
index 000000000..2d00b642d
--- /dev/null
+++ b/js/yui3/sortable/sortable-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("sortable",function(e,t){var n=function(){n.superclass.constructor.apply(this,arguments)},r="currentNode",i="opacityNode",s="container",o="id",u="zIndex",a="opacity",f="parentNode",l="nodes",c="node";e.extend(n,e.Base,{delegate:null,drop:null,initializer:function(){var t="sortable-"+e.guid(),r={container:this.get(s),nodes:this.get(l),target:!0,invalid:this.get("invalid"),dragConfig:{groups:[t]}},i;this.get("handles")&&(r.handles=this.get("handles")),i=new e.DD.Delegate(r),this.set(o,t),i.dd.plug(e.Plugin.DDProxy,{moveOnEnd:!1,cloneNode:!0}),this.drop=new e.DD.Drop({node:this.get(s),bubbleTarget:i,groups:i.dd.get("groups")}),this.drop.on("drop:enter",e.bind(this._onDropEnter,this)),i.on({"drag:start":e.bind(this._onDragStart,this),"drag:end":e.bind(this._onDragEnd,this),"drag:over":e.bind(this._onDragOver,this),"drag:drag":e.bind(this._onDrag,this)}),this.delegate=i,n.reg(this,t)},_up:null,_y:null,_onDrag:function(e){e.pageY<this._y?this._up=!0:e.pageY>this._y&&(this._up=!1),this._y=e.pageY},_onDropEnter:function(e){var t=e.drop.get(c),n=e.drag.get(c);!t.test(this.get(l))&&!n.get(f).compareTo(t)&&t.append(n)},_onDragOver:function(t){if(!t.drop.get(c).test(this.get(l)))return;if(t.drag.get(c)===t.drop.get(c))return;if(t.drag.get(c).contains(t.drop.get(c)))return;var n=!1,r,i,u,a,h,p=this.get("moveType").toLowerCase();t.drag.get(c).get(f).contains(t.drop.get(c))&&(n=!0),n&&p==="move"&&(p="insert");switch(p){case"insert":r=this._up?"before":"after",h=t.drop.get(c),e.Sortable._test(h,this.get(s))?h.append(t.drag.get(c)):h.insert(t.drag.get(c),r);break;case"swap":e.DD.DDM.swapNode(t.drag,t.drop);break;case"move":case"copy":a=e.Sortable.getSortable(t.drop.get(c).get(f));if(!a)return;e.DD.DDM.getDrop(t.drag.get(c)).addToGroup(a.get(o)),n?e.DD.DDM.swapNode(t.drag,t.drop):(this.get("moveType")==="copy"&&(i=t.drag.get(c),u=i.cloneNode(!0),u.set(o,""),t.drag.set(c,u),a.delegate.createDrop(u,[a.get(o)]),i.setStyles({top:"",left:""})),t.drop.get(c).insert(t.drag.get(c),"before"))}this.fire(p,{same:n,drag:t.drag,drop:t.drop}),this.fire("moved",{same:n,drag:t.drag,drop:t.drop})},_onDragStart:function(){var e=this.delegate,t=e.get("lastNode");t&&t.getDOMNode()&&t.setStyle(u,""),e.get(this.get(i)).setStyle(a,this.get(a)),e.get(r).setStyle(u,"999")},_onDragEnd:function(){this.delegate.get(this.get(i)).setStyle(a,1),this.delegate.get(r).setStyles({top:"",left:""}),this.sync()},plug:function(e,t){return e&&e.NAME.substring(0,4).toLowerCase()==="sort"?this.constructor.superclass.plug.call(this,e,t):this.delegate.dd.plug(e,t),this},sync:function(){return this.delegate.syncTargets(),this},destructor:function(){this.drop.destroy(),this.delegate.destroy(),n.unreg(this,this.get(o))},join:function(t,n){if(t instanceof e.Sortable){n||(n="full"),n=n.toLowerCase();var r="_join_"+n;return this[r]&&this[r](t),this}return e.error("Sortable: join needs a Sortable Instance"),this},_join_none:function(e){this.delegate.dd.removeFromGroup(e.get(o)),e.delegate.dd.removeFromGroup(this.get(o))},_join_full:function(e){this.delegate.dd.addToGroup(e.get(o)),e.delegate.dd.addToGroup(this.get(o))},_join_outer:function(e){this.delegate.dd.addToGroup(e.get(o))},_join_inner:function(e){e.delegate.dd.addToGroup(this.get(o))},getOrdering:function(t){var n=[];return e.Lang.isFunction(t)||(t=function(e){return e}),e.one(this.get(s)).all(this.get(l)).each(function(e){n.push(t(e))}),n}},{NAME:"sortable",ATTRS:{handles:{value:!1},container:{value:"body"},nodes:{value:".dd-draggable"},opacity:{value:".75"},opacityNode:{value:"currentNode"},id:{value:null},moveType:{value:"insert"},invalid:{value:""}},_sortables:{},_test:function(t,n){var r;return n instanceof e.Node?r=n===t:r=t.test(n),r},getSortable:function(t){var n=null,r=null;return t=e.one(t),r=t.get(o),r&&e.Sortable._sortables[r]?e.Sortable._sortables[r]:(e.Object.each(e.Sortable._sortables,function(r){e.Sortable._test(t,r.get(s))&&(n=r)}),n)},reg:function(t,n){n||(n=t.get(o)),e.Sortable._sortables[n]=t},unreg:function(t,r){r||(r=t.get(o));if(r&&e.Sortable._sortables[r]){delete e.Sortable._sortables[r];return}e.Object.each(e.Sortable._sortables,function(e,r){e===t&&delete n._sortables[r]})}}),e.Sortable=n},"3.7.3",{requires:["dd-delegate","dd-drop-plugin","dd-proxy"]});
diff --git a/js/yui3/stylesheet/stylesheet-min.js b/js/yui3/stylesheet/stylesheet-min.js
new file mode 100644
index 000000000..582010b17
--- /dev/null
+++ b/js/yui3/stylesheet/stylesheet-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("stylesheet",function(e,t){function v(t,r){var o,a,f,l={},h,p,m,g,y,b;if(!e.instanceOf(this,v))return new v(t,r);if(t){if(e.Node&&t instanceof e.Node)a=t._node;else if(t.nodeName)a=t;else if(s(t)){if(t&&u[t])return u[t];a=n.getElementById(t.replace(/^#/,d))}if(a&&u[e.stamp(a)])return u[e.stamp(a)]}if(!a||!/^(?:style|link)$/i.test(a.nodeName))a=n.createElement("style"),a.type="text/css";s(t)&&(t.indexOf("{")!=-1?a.styleSheet?a.styleSheet.cssText=t:a.appendChild(n.createTextNode(t)):r||(r=t));if(!a.parentNode||a.parentNode.nodeName.toLowerCase()!=="head")o=(a.ownerDocument||n).getElementsByTagName("head")[0],o.appendChild(a);f=a.sheet||a.styleSheet,h=f&&"cssRules"in f?"cssRules":"rules",m="deleteRule"in f?function(e){f.deleteRule(e)}:function(e){f.removeRule(e)},p="insertRule"in f?function(e,t,n){f.insertRule(e+" {"+t+"}",n)}:function(e,t,n){f.addRule(e,t,n)};for(g=f[h].length-1;g>=0;--g)y=f[h][g],b=y.selectorText,l[b]?(l[b].style.cssText+=";"+y.style.cssText,m(g)):l[b]=y;v.register(e.stamp(a),this),r&&v.register(r,this),e.mix(this,{getId:function(){return e.stamp(a)},enable:function(){return f.disabled=!1,this},disable:function(){return f.disabled=!0,this},isEnabled:function(){return!f.disabled},set:function(e,t){var n=l[e],r=e.split(/\s*,\s*/),i,s;if(r.length>1){for(i=r.length-1;i>=0;--i)this.set(r[i],t);return this}return v.isValidSelector(e)?(n?n.style.cssText=v.toCssText(t,n.style.cssText):(s=f[h].length,t=v.toCssText(t),t&&(p(e,t,s),l[e]=f[h][s])),this):this},unset:function(t,n){var r=l[t],s=t.split(/\s*,\s*/),o=!n,u,a;if(s.length>1){for(a=s.length-1;a>=0;--a)this.unset(s[a],n);return this}if(r){if(!o){n=e.Array(n),i.cssText=r.style.cssText;for(a=n.length-1;a>=0;--a)c(i,n[a]);i.cssText?r.style.cssText=i.cssText:o=!0}if(o){u=f[h];for(a=u.length-1;a>=0;--a)if(u[a]===r){delete l[t],m(a);break}}}return this},getCssText:function(e){var t,n,r;if(s(e))return t=l[e.split(/\s*,\s*/)[0]],t?t.style.cssText:null;n=[];for(r in l)l.hasOwnProperty(r)&&(t=l[r],n.push(t.selectorText+" {"+t.style.cssText+"}"));return n.join("\n")}})}var n=e.config.doc,r=n.createElement("p"),i=r.style,s=e.Lang.isString,o={},u={},a="cssFloat"in i?"cssFloat":"styleFloat",f,l,c,h="opacity",p="float",d="";l=h in i?function(e){e.opacity=d}:function(e){e.filter=d},i.border="1px solid red",i.border=d,c=i.borderLeft?function(e,t){var n;t!==a&&t.toLowerCase().indexOf(p)!=-1&&(t=a);if(s(e[t]))switch(t){case h:case"filter":l(e);break;case"font":e.font=e.fontStyle=e.fontVariant=e.fontWeight=e.fontSize=e.lineHeight=e.fontFamily=d;break;default:for(n in e)n.indexOf(t)===0&&(e[n]=d)}}:function(e,t){t!==a&&t.toLowerCase().indexOf(p)!=-1&&(t=a),s(e[t])&&(t===h?l(e):e[t]=d)},f=function(t,s){var o=t.styleFloat||t.cssFloat||t[p],u=e.Lang.trim,f;try{i.cssText=s||d}catch(l){r=n.createElement("p"),i=r.style,i.cssText=s||d}o&&!t[a]&&(t=e.merge(t),delete t.styleFloat,delete t.cssFloat,delete t[p],t[a]=o);for(f in t)if(t.hasOwnProperty(f))try{i[f]=u(t[f])}catch(c){}return i.cssText},e.mix(v,{toCssText:h in i?f:function(t,n){return h in t&&(t=e.merge(t,{filter:"alpha(opacity="+t.opacity*100+")"}),delete t.opacity),f(t,n)},register:function(e,t){return!!(e&&t instanceof v&&!u[e]&&(u[e]=t))},isValidSelector:function(e){var t=!1;return e&&s(e)&&(o.hasOwnProperty(e)||(o[e]=!/\S/.test(e.replace(/\s+|\s*[+~>]\s*/g," ").replace(/([^ ])\[.*?\]/g,"$1").replace(/([^ ])::?[a-z][a-z\-]+[a-z](?:\(.*?\))?/ig,"$1").replace(/(?:^| )[a-z0-6]+/ig," ").replace(/\\./g,d).replace(/[.#]\w[\w\-]*/g,d))),t=o[e]),t}},!0),e.StyleSheet=v},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/substitute/substitute-min.js b/js/yui3/substitute/substitute-min.js
new file mode 100644
index 000000000..5e1c23f9c
--- /dev/null
+++ b/js/yui3/substitute/substitute-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("substitute",function(e,t){var n=e.Lang,r="dump",i=" ",s="{",o="}",u=/(~-(\d+)-~)/g,a=/\{LBRACE\}/g,f=/\{RBRACE\}/g,l=function(t,l,c,h){var p,d,v,m,g,y,b=[],w,E,S=t.length;for(;;){p=t.lastIndexOf(s,S);if(p<0)break;d=t.indexOf(o,p);if(p+1>=d)break;w=t.substring(p+1,d),m=w,y=null,v=m.indexOf(i),v>-1&&(y=m.substring(v+1),m=m.substring(0,v)),g=l[m],c&&(g=c(m,g,y)),n.isObject(g)?e.dump?n.isArray(g)?g=e.dump(g,parseInt(y,10)):(y=y||"",E=y.indexOf(r),E>-1&&(y=y.substring(4)),g.toString===Object.prototype.toString||E>-1?g=e.dump(g,parseInt(y,10)):g=g.toString()):g=g.toString():n.isUndefined(g)&&(g="~-"+b.length+"-~",b.push(w)),t=t.substring(0,p)+g+t.substring(d+1),h||(S=p-1)}return t.replace(u,function(e,t,n){return s+b[parseInt(n,10)]+o}).replace(a,s).replace(f,o)};e.substitute=l,n.substitute=l},"3.7.3",{requires:["yui-base"],optional:["dump"]});
diff --git a/js/yui3/swf/swf-min.js b/js/yui3/swf/swf-min.js
new file mode 100644
index 000000000..ac38aa2e8
--- /dev/null
+++ b/js/yui3/swf/swf-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("swf",function(e,t){function d(t,n,d){this._id=e.guid("yuiswf");var v=this._id,m=o.one(t),d=d||{},g=d.version||l,y=(g+"").split("."),b=r.isFlashVersionAtLeast(parseInt(y[0],10),parseInt(y[1],10),parseInt(y[2],10)),w=r.isFlashVersionAtLeast(8,0,0),E=w&&!b&&d.useExpressInstall,S=E?c:n,x="<object ",T,N,C="yId="+e.id+"&YUISwfId="+v+"&YUIBridgeCallback="+h+"&allowedDomain="+document.location.hostname;e.SWF._instances[v]=this;if(m&&(b||E)&&S){x+='id="'+v+'" ',s.ie?x+='classid="'+a+'" ':x+='type="'+f+'" data="'+u.html(S)+'" ',T="100%",N="100%",x+='width="'+T+'" height="'+N+'">',s.ie&&(x+='<param name="movie" value="'+u.html(S)+'"/>');for(var k in d.fixedAttributes)p.hasOwnProperty(k)&&(x+='<param name="'+u.html(k)+'" value="'+u.html(d.fixedAttributes[k])+'"/>');for(var L in d.flashVars){var A=d.flashVars[L];i.isString(A)&&(C+="&"+u.html(L)+"="+u.html(encodeURIComponent(A)))}C&&(x+='<param name="flashVars" value="'+C+'"/>'),x+="</object>",m.set("innerHTML",x),this._swf=o.one("#"+v)}else{var O={};O.type="wrongflashversion",this.publish("wrongflashversion",{fireOnce:!0}),this.fire("wrongflashversion",O)}}var n=e.Event,r=e.SWFDetect,i=e.Lang,s=e.UA,o=e.Node,u=e.Escape,a="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000",f="application/x-shockwave-flash",l="10.0.22",c="http://fpdownload.macromedia.com/pub/flashplayer/update/current/swf/autoUpdater.swf?"+Math.random(),h="SWF.eventHandler",p={align:"",allowFullScreen:"",allowNetworking:"",allowScriptAccess:"",base:"",bgcolor:"",loop:"",menu:"",name:"",play:"",quality:"",salign:"",scale:"",tabindex:"",wmode:""};d._instances=d._instances||{},d.eventHandler=function(e,t){d._instances[e]._eventHandler(t)},d.prototype={_eventHandler:function(e){e.type==="swfReady"?(this.publish("swfReady",{fireOnce:!0}),this.fire("swfReady",e)):e.type!=="log"&&this.fire(e.type,e)},callSWF:function(e,t){return t||(t=[]),this._swf._node[e]?this._swf._node[e].apply(this._swf._node,t):null},toString:function(){return"SWF "+this._id}},e.augment(d,e.EventTarget),e.SWF=d},"3.7.3",{requires:["event-custom","node","swfdetect","escape"]});
diff --git a/js/yui3/swfdetect/swfdetect-min.js b/js/yui3/swfdetect/swfdetect-min.js
new file mode 100644
index 000000000..9506af3e2
--- /dev/null
+++ b/js/yui3/swfdetect/swfdetect-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("swfdetect",function(e,t){function c(e){return parseInt(e,10)}function h(e){i.isNumber(c(e[0]))&&(r.flashMajor=e[0]),i.isNumber(c(e[1]))&&(r.flashMinor=e[1]),i.isNumber(c(e[2]))&&(r.flashRev=e[2])}var n=0,r=e.UA,i=e.Lang,s="ShockwaveFlash",o,u,a,f,l;if(r.gecko||r.webkit||r.opera){if(o=navigator.mimeTypes["application/x-shockwave-flash"])if(u=o.enabledPlugin)a=u.description.replace(/\s[rd]/g,".").replace(/[A-Za-z\s]+/g,"").split("."),h(a)}else if(r.ie){try{f=new ActiveXObject(s+"."+s+".6"),f.AllowScriptAccess="always"}catch(p){f!==null&&(n=6)}if(n===0)try{l=new ActiveXObject(s+"."+s),a=l.GetVariable("$version").replace(/[A-Za-z\s]+/g,"").split(","),h(a)}catch(d){}}e.SWFDetect={getFlashVersion:function(){return String(r.flashMajor)+"."+String(r.flashMinor)+"."+String(r.flashRev)},isFlashVersionAtLeast:function(e,t,n){var i=c(r.flashMajor),s=c(r.flashMinor),o=c(r.flashRev);return e=c(e||0),t=c(t||0),n=c(n||0),e===i?t===s?n<=o:t<s:e<i}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/tabview-base/assets/tabview-core.css b/js/yui3/tabview-base/assets/tabview-core.css
new file mode 100644
index 000000000..96d2628d1
--- /dev/null
+++ b/js/yui3/tabview-base/assets/tabview-core.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display:none;
+}
+
+.yui3-tab-panel-selected {
+ display:block;
+}
+
+.yui3-tabview-list,
+.yui3-tab {
+ margin:0;
+ padding:0;
+ list-style:none;
+}
+
+.yui3-tabview {
+ position:relative; /* contain absolute positioned tabs (left/right) */
+}
+
+.yui3-tabview,
+.yui3-tabview-list,
+.yui3-tabview-panel,
+.yui3-tab,
+.yui3-tab-panel { /* IE: kill space between horizontal tabs */
+ zoom:1;
+}
+
+.yui3-tab {
+ display:inline-block;
+ *display:inline; /* IE */
+ vertical-align:bottom; /* safari: for overlap */
+ cursor:pointer;
+}
+
+.yui3-tab-label {
+ display:block;
+ display:inline-block;
+ padding: 6px 10px;
+ position:relative; /* IE: to allow overlap */
+ text-decoration: none;
+ vertical-align:bottom; /* safari: for overlap */
+}
diff --git a/js/yui3/tabview-base/assets/tabview.css b/js/yui3/tabview-base/assets/tabview.css
new file mode 100644
index 000000000..552623a06
--- /dev/null
+++ b/js/yui3/tabview-base/assets/tabview.css
@@ -0,0 +1,28 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display: none;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-panel-selected {
+ background: yellow;
+ display: block;
+}
+
+.yui3-tab {
+ display: inline-block;
+ margin-right: 0.5em;
+ zoom: 1;
+};
diff --git a/js/yui3/tabview-base/tabview-base-min.js b/js/yui3/tabview-base/tabview-base-min.js
new file mode 100644
index 000000000..a602410ab
--- /dev/null
+++ b/js/yui3/tabview-base/tabview-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("tabview-base",function(e,t){var n=e.ClassNameManager.getClassName,r="tabview",i="tab",s="content",o="panel",u="selected",a={},f=".",l={tabview:n(r),tabviewPanel:n(r,o),tabviewList:n(r,"list"),tab:n(i),tabLabel:n(i,"label"),tabPanel:n(i,o),selectedTab:n(i,u),selectedPanel:n(i,o,u)},c={tabview:f+l.tabview,tabviewList:"> ul",tab:"> ul > li",tabLabel:"> ul > li > a",tabviewPanel:"> div",tabPanel:"> div > div",selectedTab:"> ul > "+f+l.selectedTab,selectedPanel:"> div "+f+l.selectedPanel},h=function(e){this.init.apply(this,arguments)};h.NAME="tabviewBase",h._queries=c,h._classNames=l,e.mix(h.prototype,{init:function(t){t=t||a,this._node=t.host||e.one(t.node),this.refresh()},initClassNames:function(t){e.Object.each(c,function(e,n){if(l[n]){var r=this.all(e);t!==undefined&&(r=r.item(t)),r&&r.addClass(l[n])}},this._node),this._node.addClass(l.tabview)},_select:function(e){var t=this._node,n=t.one(c.selectedTab),r=t.one(c.selectedPanel),i=t.all(c.tab).item(e),s=t.all(c.tabPanel).item(e);n&&n.removeClass(l.selectedTab),r&&r.removeClass(l.selectedPanel),i&&i.addClass(l.selectedTab),s&&s.addClass(l.selectedPanel)},initState:function(){var e=this._node,t=e.one(c.selectedTab),n=t?e.all(c.tab).indexOf(t):0;this._select(n)},_scrubTextNodes:function(){this._node.one(c.tabviewList).get("childNodes").each(function(e){e.get("nodeType")===3&&e.remove()})},refresh:function(){this._scrubTextNodes(),this.initClassNames(),this.initState(),this.initEvents()},tabEventName:"click",initEvents:function(){this._node.delegate(this.tabEventName,this.onTabEvent,c.tab,this)},onTabEvent:function(e){e.preventDefault(),this._select(this._node.all(c.tab).indexOf(e.currentTarget))},destroy:function(){this._node.detach(this.tabEventName)}}),e.TabviewBase=h},"3.7.3",{requires:["node-event-delegate","classnamemanager","skin-sam-tabview"]});
diff --git a/js/yui3/tabview-plugin/assets/tabview-core.css b/js/yui3/tabview-plugin/assets/tabview-core.css
new file mode 100644
index 000000000..96d2628d1
--- /dev/null
+++ b/js/yui3/tabview-plugin/assets/tabview-core.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display:none;
+}
+
+.yui3-tab-panel-selected {
+ display:block;
+}
+
+.yui3-tabview-list,
+.yui3-tab {
+ margin:0;
+ padding:0;
+ list-style:none;
+}
+
+.yui3-tabview {
+ position:relative; /* contain absolute positioned tabs (left/right) */
+}
+
+.yui3-tabview,
+.yui3-tabview-list,
+.yui3-tabview-panel,
+.yui3-tab,
+.yui3-tab-panel { /* IE: kill space between horizontal tabs */
+ zoom:1;
+}
+
+.yui3-tab {
+ display:inline-block;
+ *display:inline; /* IE */
+ vertical-align:bottom; /* safari: for overlap */
+ cursor:pointer;
+}
+
+.yui3-tab-label {
+ display:block;
+ display:inline-block;
+ padding: 6px 10px;
+ position:relative; /* IE: to allow overlap */
+ text-decoration: none;
+ vertical-align:bottom; /* safari: for overlap */
+}
diff --git a/js/yui3/tabview-plugin/assets/tabview.css b/js/yui3/tabview-plugin/assets/tabview.css
new file mode 100644
index 000000000..552623a06
--- /dev/null
+++ b/js/yui3/tabview-plugin/assets/tabview.css
@@ -0,0 +1,28 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display: none;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-panel-selected {
+ background: yellow;
+ display: block;
+}
+
+.yui3-tab {
+ display: inline-block;
+ margin-right: 0.5em;
+ zoom: 1;
+};
diff --git a/js/yui3/tabview-plugin/tabview-plugin-min.js b/js/yui3/tabview-plugin/tabview-plugin-min.js
new file mode 100644
index 000000000..2c3789ce3
--- /dev/null
+++ b/js/yui3/tabview-plugin/tabview-plugin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("tabview-plugin",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}n.NAME="tabviewPlugin",n.NS="tabs",e.extend(n,e.TabviewBase),e.namespace("Plugin"),e.Plugin.Tabview=n},"3.7.3",{requires:["tabview-base"]});
diff --git a/js/yui3/tabview/assets/skins/night/tabview.css b/js/yui3/tabview/assets/skins/night/tabview.css
new file mode 100644
index 000000000..a27afe3b2
--- /dev/null
+++ b/js/yui3/tabview/assets/skins/night/tabview.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel{display:none}.yui3-tab-panel-selected{display:block}.yui3-tabview-list,.yui3-tab{margin:0;padding:0;list-style:none}.yui3-tabview{position:relative}.yui3-tabview,.yui3-tabview-list,.yui3-tabview-panel,.yui3-tab,.yui3-tab-panel{zoom:1}.yui3-tab{display:inline-block;*display:inline;vertical-align:bottom;cursor:pointer}.yui3-tab-label{display:block;display:inline-block;padding:6px 10px;position:relative;text-decoration:none;vertical-align:bottom}.yui3-skin-night .yui3-tabview-panel{background-color:#333;color:#808080;padding:1px}.yui3-skin-night .yui3-tab-panel p{margin:10px}.yui3-skin-night .yui3-tabview-list{background-color:#0f0f0f;border-top:1px solid #000;text-align:center;height:46px;background:-moz-linear-gradient(0% 100% 90deg,#0f0f0f 0,#1e1e1e 96%,#292929 100%);background:-webkit-gradient(linear,left bottom,left top,from(#0f0f0f),color-stop(0.96,#1e1e1e),to(#292929))}.yui3-skin-night .yui3-tabview-list li{margin-top:8px}.yui3-skin-night .yui3-tabview-list li a{border:solid 1px #0c0c0c;border-right-style:none;-moz-box-shadow:0 1px #222;-webkit-box-shadow:0 1px #222;box-shadow:0 1px #222;text-shadow:0 -1px 0 rgba(0,0,0,0.7);font-size:85%;text-align:center;color:#fff;padding:6px 28px;background-color:#555658;background:-moz-linear-gradient(0% 100% 90deg,#343536 0,#555658 96%,#3e3f41 100%);background:-webkit-gradient(linear,left bottom,left top,from(#343536),color-stop(0.96,#555658),to(#3e3f41))}.yui3-skin-night .yui3-tabview-list li.yui3-tab-selected a{background-color:#2b2d2d;background:-moz-linear-gradient(0% 100% 90deg,#242526 0,#3b3c3d 96%,#2c2d2f 100%);background:-webkit-gradient(linear,left bottom,left top,from(#242526),color-stop(0.96,#3b3c3d),to(#2c2d2f))}.yui3-skin-night .yui3-tabview-list li:first-child a{-moz-border-radius:6px 0 0 6px;-webkit-border-radius:6px 0 0 6px;border-radius:6px 0 0 6px}.yui3-skin-night .yui3-tabview-list li:last-child a{border-right-style:solid;-moz-border-radius:0 6px 6px 0;-webkit-border-radius:0 6px 6px 0;border-radius:0 6px 6px 0}#yui3-css-stamp.skin-night-tabview{display:none}
diff --git a/js/yui3/tabview/assets/skins/sam/tabview.css b/js/yui3/tabview/assets/skins/sam/tabview.css
new file mode 100644
index 000000000..e5fa15c4a
--- /dev/null
+++ b/js/yui3/tabview/assets/skins/sam/tabview.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel{display:none}.yui3-tab-panel-selected{display:block}.yui3-tabview-list,.yui3-tab{margin:0;padding:0;list-style:none}.yui3-tabview{position:relative}.yui3-tabview,.yui3-tabview-list,.yui3-tabview-panel,.yui3-tab,.yui3-tab-panel{zoom:1}.yui3-tab{display:inline-block;*display:inline;vertical-align:bottom;cursor:pointer}.yui3-tab-label{display:block;display:inline-block;padding:6px 10px;position:relative;text-decoration:none;vertical-align:bottom}.yui3-skin-sam .yui3-tabview-list{border:solid #2647a0;border-width:0 0 5px;zoom:1}.yui3-skin-sam .yui3-tab{margin:0 .2em 0 0;padding:1px 0 0;zoom:1}.yui3-skin-sam .yui3-tab-selected{margin-bottom:-1px}.yui3-skin-sam .yui3-tab-label{background:#d8d8d8 url(../../../../assets/skins/sam/sprite.png) repeat-x;border:solid #a3a3a3;border-width:1px 1px 0 1px;color:#000;cursor:pointer;font-size:85%;padding:.3em .75em;text-decoration:none}.yui3-skin-sam .yui3-tab-label:hover,.yui3-skin-sam .yui3-tab-label:focus{background:#bfdaff url(../../../../assets/skins/sam/sprite.png) repeat-x left -1300px;outline:0}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:focus,.yui3-skin-sam .yui3-tab-selected .yui3-tab-label:hover{background:#2647a0 url(../../../../assets/skins/sam/sprite.png) repeat-x left -1400px;color:#fff}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{padding:.4em .75em}.yui3-skin-sam .yui3-tab-selected .yui3-tab-label{border-color:#243356}.yui3-skin-sam .yui3-tabview-panel{background:#edf5ff}.yui3-skin-sam .yui3-tabview-panel{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em}#yui3-css-stamp.skin-sam-tabview{display:none}
diff --git a/js/yui3/tabview/assets/tabview-core.css b/js/yui3/tabview/assets/tabview-core.css
new file mode 100644
index 000000000..96d2628d1
--- /dev/null
+++ b/js/yui3/tabview/assets/tabview-core.css
@@ -0,0 +1,48 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display:none;
+}
+
+.yui3-tab-panel-selected {
+ display:block;
+}
+
+.yui3-tabview-list,
+.yui3-tab {
+ margin:0;
+ padding:0;
+ list-style:none;
+}
+
+.yui3-tabview {
+ position:relative; /* contain absolute positioned tabs (left/right) */
+}
+
+.yui3-tabview,
+.yui3-tabview-list,
+.yui3-tabview-panel,
+.yui3-tab,
+.yui3-tab-panel { /* IE: kill space between horizontal tabs */
+ zoom:1;
+}
+
+.yui3-tab {
+ display:inline-block;
+ *display:inline; /* IE */
+ vertical-align:bottom; /* safari: for overlap */
+ cursor:pointer;
+}
+
+.yui3-tab-label {
+ display:block;
+ display:inline-block;
+ padding: 6px 10px;
+ position:relative; /* IE: to allow overlap */
+ text-decoration: none;
+ vertical-align:bottom; /* safari: for overlap */
+}
diff --git a/js/yui3/tabview/assets/tabview.css b/js/yui3/tabview/assets/tabview.css
new file mode 100644
index 000000000..552623a06
--- /dev/null
+++ b/js/yui3/tabview/assets/tabview.css
@@ -0,0 +1,28 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-tab-panel {
+ display: none;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-selected {
+ background: yellow;
+}
+
+.yui3-tab-panel-selected {
+ background: yellow;
+ display: block;
+}
+
+.yui3-tab {
+ display: inline-block;
+ margin-right: 0.5em;
+ zoom: 1;
+};
diff --git a/js/yui3/tabview/tabview-min.js b/js/yui3/tabview/tabview-min.js
new file mode 100644
index 000000000..15ae0d90f
--- /dev/null
+++ b/js/yui3/tabview/tabview-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("tabview",function(e,t){var n=e.TabviewBase._queries,r=e.TabviewBase._classNames,i=".",s=e.ClassNameManager.getClassName,o=e.Base.create("tabView",e.Widget,[e.WidgetParent],{_afterChildAdded:function(e){this.get("contentBox").focusManager.refresh()},_defListNodeValueFn:function(){return e.Node.create(o.LIST_TEMPLATE)},_defPanelNodeValueFn:function(){return e.Node.create(o.PANEL_TEMPLATE)},_afterChildRemoved:function(e){var t=e.index,n=this.get("selection");n||(n=this.item(t-1)||this.item(0),n&&n.set("selected",1)),this.get("contentBox").focusManager.refresh()},_initAria:function(){var e=this.get("contentBox"),t=e.one(n.tabviewList);t&&t.setAttrs({role:"tablist"})},bindUI:function(){this.get("contentBox").plug(e.Plugin.NodeFocusManager,{descendants:i+r.tabLabel,keys:{next:"down:39",previous:"down:37"},circular:!0}),this.after("render",this._setDefSelection),this.after("addChild",this._afterChildAdded),this.after("removeChild",this._afterChildRemoved)},renderUI:function(){var e=this.get("contentBox");this._renderListBox(e),this._renderPanelBox(e),this._childrenContainer=this.get("listNode"),this._renderTabs(e)},_setDefSelection:function(e){var t=this.get("selection")||this.item(0);this.some(function(e){if(e.get("selected"))return t=e,!0}),t&&(this.set("selection",t),t.set("selected",1))},_renderListBox:function(e){var t=this.get("listNode");t.inDoc()||e.append(t)},_renderPanelBox:function(e){var t=this.get("panelNode");t.inDoc()||e.append(t)},_renderTabs:function(e){var t=e.all(n.tab),s=this.get("panelNode"),o=s?this.get("panelNode").get("children"):null,u=this;t&&(t.addClass(r.tab),e.all(n.tabLabel).addClass(r.tabLabel),e.all(n.tabPanel).addClass(r.tabPanel),t.each(function(e,t){var n=o?o.item(t):null;u.add({boundingBox:e,contentBox:e.one(i+r.tabLabel),label:e.one(i+r.tabLabel).get("text"),panelNode:n})}))}},{LIST_TEMPLATE:'<ul class="'+r.tabviewList+'"></ul>',PANEL_TEMPLATE:'<div class="'+r.tabviewPanel+'"></div>',ATTRS:{defaultChildType:{value:"Tab"},listNode:{setter:function(t){return t=e.one(t),t&&t.addClass(r.tabviewList),t},valueFn:"_defListNodeValueFn"},panelNode:{setter:function(t){return t=e.one(t),t&&t.addClass(r.tabviewPanel),t},valueFn:"_defPanelNodeValueFn"},tabIndex:{value:null}},HTML_PARSER:{listNode:n.tabviewList,panelNode:n.tabviewPanel}});e.TabView=o;var u=e.Lang,n=e.TabviewBase._queries,r=e.TabviewBase._classNames,s=e.ClassNameManager.getClassName;e.Tab=e.Base.create("tab",e.Widget,[e.WidgetChild],{BOUNDING_TEMPLATE:'<li class="'+r.tab+'"></li>',CONTENT_TEMPLATE:'<a class="'+r.tabLabel+'"></a>',PANEL_TEMPLATE:'<div class="'+r.tabPanel+'"></div>',_uiSetSelectedPanel:function(e){this.get("panelNode").toggleClass(r.selectedPanel,e)},_afterTabSelectedChange:function(e){this._uiSetSelectedPanel(e.newVal)},_afterParentChange:function(e){e.newVal?this._add():this._remove()},_initAria:function(){var t=this.get("contentBox"),n=t.get("id"),r=this.get("panelNode");n||(n=e.guid(),t.set("id",n)),t.set("role","tab"),t.get("parentNode").set("role","presentation"),r.setAttrs({role:"tabpanel","aria-labelledby":n})},syncUI:function(){this.set("label",this.get("label")),this.set("content",this.get("content")),this._uiSetSelectedPanel(this.get("selected"))},bindUI:function(){this.after("selectedChange",this._afterTabSelectedChange),this.after("parentChange",this._afterParentChange)},renderUI:function(){this._renderPanel(),this._initAria()},_renderPanel:function(){this.get("parent").get("panelNode").appendChild(this.get("panelNode"))},_add:function(){var e=this.get("parent").get("contentBox"),t=e.get("listNode"),n=e.get("panelNode");t&&t.appendChild(this.get("boundingBox")),n&&n.appendChild(this.get("panelNode"))},_remove:function(){this.get("boundingBox").remove(),this.get("panelNode").remove()},_onActivate:function(e){e.target===this&&(e.domEvent.preventDefault(),e.target.set("selected",1))},initializer:function(){this.publish(this.get("triggerEvent"),{defaultFn:this._onActivate})},_defLabelSetter:function(e){return this.get("contentBox").setContent(e),e},_defContentSetter:function(e){return this.get("panelNode").setContent(e),e},_defContentGetter:function(e){return this.get("panelNode").getContent()},_defPanelNodeValueFn:function(){var t=this.get("contentBox").get("href")||"",n=this.get("parent"),i=t.indexOf("#"),s;return t=t.substr(i),t.charAt(0)==="#"&&(s=e.one(t),s&&s.addClass(r.tabPanel)),!s&&n&&(s=n.get("panelNode").get("children").item(this.get("index"))),s||(s=e.Node.create(this.PANEL_TEMPLATE)),s}},{ATTRS:{triggerEvent:{value:"click"},label:{setter:"_defLabelSetter",validator:u.isString},content:{setter:"_defContentSetter",getter:"_defContentGetter"},panelNode:{setter:function(t){return t=e.one(t),t&&t.addClass(r.tabPanel),t},valueFn:"_defPanelNodeValueFn"},tabIndex:{value:null,validator:"_validTabIndex"}},HTML_PARSER:{selected:function(e){var t=this.get("boundingBox").hasClass(r.selectedTab)?1:0;return t}}})},"3.7.3",{requires:["widget","widget-parent","widget-child","tabview-base","node-pluginhost","node-focusmanager"],skinnable:!0});
diff --git a/js/yui3/test-console/assets/skins/sam/test-console.css b/js/yui3/test-console/assets/skins/sam/test-console.css
new file mode 100644
index 000000000..9f1fb25dc
--- /dev/null
+++ b/js/yui3/test-console/assets/skins/sam/test-console.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-testconsole .yui3-console-entry{min-height:inherit;padding:5px}.yui3-testconsole .yui3-console-controls{display:none}.yui3-skin-sam .yui3-testconsole .yui3-console-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd,.yui3-skin-sam .yui3-testconsole .yui3-console-entry,.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-categories,.yui3-skin-sam .yui3-testconsole .yui3-console-ft .yui3-console-filters-sources,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{background:0;border:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.yui3-skin-sam .yui3-testconsole-content,.yui3-skin-sam .yui3-testconsole .yui3-console-bd{color:#333;font:13px/1.4 Helvetica,'DejaVu Sans','Bitstream Vera Sans',Arial,sans-serif}.yui3-skin-sam .yui3-testconsole-content{border:1px solid #afafaf}.yui3-skin-sam .yui3-testconsole .yui3-console-entry{border-bottom:1px solid #eaeaea;font-family:Menlo,Inconsolata,Consolas,'DejaVu Mono','Bitstream Vera Sans Mono',monospace;font-size:11px}.yui3-skin-sam .yui3-testconsole .yui3-console-ft{border-top:1px solid}.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-bottom:1px solid;*zoom:1}.yui3-skin-sam .yui3-testconsole.yui3-console-collapsed .yui3-console-hd{border:0}.yui3-skin-sam .yui3-testconsole .yui3-console-ft,.yui3-skin-sam .yui3-testconsole .yui3-console-hd{border-color:#cfcfcf}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-fail{background-color:#ffe0e0;border-bottom-color:#ffc5c4}.yui3-skin-sam .yui3-testconsole .yui3-testconsole-entry-pass{background-color:#ecffea;border-bottom-color:#d1ffcc}#yui3-css-stamp.skin-sam-test-console{display:none}
diff --git a/js/yui3/test-console/assets/test-console-core.css b/js/yui3/test-console/assets/test-console-core.css
new file mode 100644
index 000000000..00ad9b583
--- /dev/null
+++ b/js/yui3/test-console/assets/test-console-core.css
@@ -0,0 +1,14 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-testconsole .yui3-console-entry {
+ min-height: inherit;
+ padding: 5px;
+}
+
+.yui3-testconsole .yui3-console-controls {
+ display: none;
+}
diff --git a/js/yui3/test-console/test-console-min.js b/js/yui3/test-console/test-console-min.js
new file mode 100644
index 000000000..eb0653158
--- /dev/null
+++ b/js/yui3/test-console/test-console-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("test-console",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}e.namespace("Test").Console=e.extend(n,e.Console,{initializer:function(t){this.on("entry",this._onEntry),this.plug(e.Plugin.ConsoleFilters,{category:e.merge({info:!0,pass:!1,fail:!0,status:!1},t&&t.filters||{}),defaultVisibility:!1,source:{TestRunner:!0}}),e.Test.Runner.on("complete",e.bind(this._parseCoverage,this))},_isIstanbul:function(e){var t=Object.keys(e)[0],n=!1;return e[t].s!==undefined&&e[t].fnMap!==undefined&&(n=!0),e.s!==undefined&&e.fnMap!==undefined&&(n=!0),n},parseYUITestCoverage:function(t){var n={lines:{hit:0,miss:0,total:0,percent:0},functions:{hit:0,miss:0,total:0,percent:0}},r;e.Object.each(t,function(e){n.lines.total+=e.coveredLines,n.lines.hit+=e.calledLines,n.lines.miss+=e.coveredLines-e.calledLines,n.lines.percent=Math.floor(n.lines.hit/n.lines.total*100),n.functions.total+=e.coveredFunctions,n.functions.hit+=e.calledFunctions,n.functions.miss+=e.coveredFunctions-e.calledFunctions,n.functions.percent=Math.floor(n.functions.hit/n.functions.total*100)}),r="Lines: Hit:"+n.lines.hit+" Missed:"+n.lines.miss+" Total:"+n.lines.total+" Percent:"+n.lines.percent+"%\n",r+="Functions: Hit:"+n.functions.hit+" Missed:"+n.functions.miss+" Total:"+n.functions.total+" Percent:"+n.functions.percent+"%",this.log("Coverage: "+r,"info","TestRunner")},_blankSummary:function(){return{lines:{total:0,covered:0,pct:"Unknown"},statements:{total:0,covered:0,pct:"Unknown"},functions:{total:0,covered:0,pct:"Unknown"},branches:{total:0,covered:0,pct:"Unknown"}}},_addDerivedInfoForFile:function(t){var n=t.statementMap,r=t.s,i;t.l||(t.l=i={},e.Object.each(r,function(e,t){var s=n[t].start.line,o=r[t],u=i[s];if(typeof u=="undefined"||u<o)i[s]=o}))},_percent:function(e,t){var n,r=100;return t>0&&(n=1e5*e/t+5,r=Math.floor(n/10)/100),r},_computeSimpleTotals:function(t,n){var r=t[n],i={total:0,covered:0};return e.Object.each(r,function(e){i.total+=1,e&&(i.covered+=1)}),i.pct=this._percent(i.covered,i.total),i},_computeBranchTotals:function(t){var n=t.b,r={total:0,covered:0};return e.Object.each(n,function(t){var n=e.Array.filter(t,function(e){return e>0});r.total+=t.length,r.covered+=n.length}),r.pct=this._percent(r.covered,r.total),r},parseIstanbul:function(t){var n=this,r="Coverage Report:\n";e.Object.each(t,function(t,i){var s=n._blankSummary();n._addDerivedInfoForFile(t),s.lines=n._computeSimpleTotals(t,"l"),s.functions=n._computeSimpleTotals(t,"f"),s.statements=n._computeSimpleTotals(t,"s"),s.branches=n._computeBranchTotals(t),r+=i+":\n",e.Array.each(["lines","functions","statements","branches"],function(e){r+=" "+e+": "+s[e].covered+"/"+s[e].total+" : "+s[e].pct+"%\n"})}),this.log(r,"info","TestRunner")},_parseCoverage:function(){var t=e.Test.Runner.getCoverage();if(!t)return;this._isIstanbul(t)?this.parseIstanbul(t):this.parseYUITestCoverage(t)},_onEntry:function(e){var t=e.message;t.category==="info"&&/\s(?:case|suite)\s|yuitests\d+|began/.test(t.message)?t.category="status":t.category==="fail"&&this.printBuffer()}},{NAME:"testConsole",ATTRS:{entryTemplate:{value:'<div class="{entry_class} {cat_class} {src_class}"><div class="{entry_content_class}">{message}</div></div>'},height:{value:"350px"},newestOnTop:{value:!1},style:{value:"block"},width:{value:e.UA.ie&&e.UA.ie<9?"100%":"inherit"}}})},"3.7.3",{requires:["console-filters","test","array-extras"],skinnable:!0});
diff --git a/js/yui3/test/test-min.js b/js/yui3/test/test-min.js
new file mode 100644
index 000000000..d0aabd966
--- /dev/null
+++ b/js/yui3/test/test-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("test",function(e,t){YUI.YUITest?e.Test=YUI.YUITest:(YUITest={version:"3.7.3",guid:function(t){return e.guid(t)}},e.namespace("Test"),YUITest.Object=e.Object,YUITest.Array=e.Array,YUITest.Util={mix:e.mix,JSON:e.JSON},YUITest.EventTarget=function(){this._handlers={}},YUITest.EventTarget.prototype={constructor:YUITest.EventTarget,attach:function(e,t){typeof this._handlers[e]=="undefined"&&(this._handlers[e]=[]),this._handlers[e].push(t)},subscribe:function(e,t){this.attach.apply(this,arguments)},fire:function(e){typeof e=="string"&&(e={type:e}),e.target||(e.target=this);if(!e.type)throw new Error("Event object missing 'type' property.");if(this._handlers[e.type]instanceof Array){var t=this._handlers[e.type];for(var n=0,r=t.length;n<r;n++)t[n].call(this,e)}},detach:function(e,t){if(this._handlers[e]instanceof Array){var n=this._handlers[e];for(var r=0,i=n.length;r<i;r++)if(n[r]===t){n.splice(r,1);break}}},unsubscribe:function(e,t){this.detach.apply(this,arguments)}},YUITest.TestSuite=function(e){this.name="",this.items=[];if(typeof e=="string")this.name=e;else if(e instanceof Object)for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);if(this.name===""||!this.name)this.name=YUITest.guid("testSuite_")},YUITest.TestSuite.prototype={constructor:YUITest.TestSuite,add:function(e){return(e instanceof YUITest.TestSuite||e instanceof YUITest.TestCase)&&this.items.push(e),this},setUp:function(){},tearDown:function(){}},YUITest.TestCase=function(e){this._should={};for(var t in e)this[t]=e[t];typeof this.name!="string"&&(this.name=YUITest.guid("testCase_"))},YUITest.TestCase.prototype={constructor:YUITest.TestCase,callback:function(){return YUITest.TestRunner.callback.apply(YUITest.TestRunner,arguments)},resume:function(e){YUITest.TestRunner.resume(e)},wait:function(e,t){var n=typeof e=="number"?e:t;throw n=typeof n=="number"?n:1e4,typeof e=="function"?new YUITest.Wait(e,n):new YUITest.Wait(function(){YUITest.Assert.fail("Timeout: wait() called but resume() never called.")},n)},assert:function(e,t){YUITest.Assert._increment();if(!e)throw new YUITest.AssertionError(YUITest.Assert._formatMessage(t,"Assertion failed."))},fail:function(e){YUITest.Assert.fail(e)},init:function(){},destroy:function(){},setUp:function(){},tearDown:function(){}},YUITest.TestFormat=function(){function e(e){return e.replace(/[<>"'&]/g,function(e){switch(e){case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case"'":return"&apos;";case"&":return"&amp;"}})}return{JSON:function(e){return YUITest.Util.JSON.stringify(e)},XML:function(t){function n(t){var r="<"+t.type+' name="'+e(t.name)+'"';typeof t.duration=="number"&&(r+=' duration="'+t.duration+'"');if(t.type=="test")r+=' result="'+t.result+'" message="'+e(t.message)+'">';else{r+=' passed="'+t.passed+'" failed="'+t.failed+'" ignored="'+t.ignored+'" total="'+t.total+'">';for(var i in t)t.hasOwnProperty(i)&&t[i]&&typeof t[i]=="object"&&!(t[i]instanceof Array)&&(r+=n(t[i]))}return r+="</"+t.type+">",r}return'<?xml version="1.0" encoding="UTF-8"?>'+n(t)},JUnitXML:function(t){function n(t){var r="";switch(t.type){case"test":t.result!="ignore"&&(r='<testcase name="'+e(t.name)+'" time="'+t.duration/1e3+'">',t.result=="fail"&&(r+='<failure message="'+e(t.message)+'"><![CDATA['+t.message+"]]></failure>"),r+="</testcase>");break;case"testcase":r='<testsuite name="'+e(t.name)+'" tests="'+t.total+'" failures="'+t.failed+'" time="'+t.duration/1e3+'">';for(var i in t)t.hasOwnProperty(i)&&t[i]&&typeof t[i]=="object"&&!(t[i]instanceof Array)&&(r+=n(t[i]));r+="</testsuite>";break;case"testsuite":for(var i in t)t.hasOwnProperty(i)&&t[i]&&typeof t[i]=="object"&&!(t[i]instanceof Array)&&(r+=n(t[i]));break;case"report":r="<testsuites>";for(var i in t)t.hasOwnProperty(i)&&t[i]&&typeof t[i]=="object"&&!(t[i]instanceof Array)&&(r+=n(t[i]));r+="</testsuites>"}return r}return'<?xml version="1.0" encoding="UTF-8"?>'+n(t)},TAP:function(e){function n(e){var r="";switch(e.type){case"test":e.result!="ignore"?(r="ok "+t++ +" - "+e.name,e.result=="fail"&&(r="not "+r+" - "+e.message),r+="\n"):r="#Ignored test "+e.name+"\n";break;case"testcase":r="#Begin testcase "+e.name+"("+e.failed+" failed of "+e.total+")\n";for(var i in e)e.hasOwnProperty(i)&&e[i]&&typeof e[i]=="object"&&!(e[i]instanceof Array)&&(r+=n(e[i]));r+="#End testcase "+e.name+"\n";break;case"testsuite":r="#Begin testsuite "+e.name+"("+e.failed+" failed of "+e.total+")\n";for(var i in e)e.hasOwnProperty(i)&&e[i]&&typeof e[i]=="object"&&!(e[i]instanceof Array)&&(r+=n(e[i]));r+="#End testsuite "+e.name+"\n";break;case"report":for(var i in e)e.hasOwnProperty(i)&&e[i]&&typeof e[i]=="object"&&!(e[i]instanceof Array)&&(r+=n(e[i]))}return r}var t=1;return"1.."+e.total+"\n"+n(e)}}}(),YUITest.Reporter=function(e,t){this.url=e,this.format=t||YUITest.TestFormat.XML,this._fields=new Object,this._form=null,this._iframe=null},YUITest.Reporter.prototype={constructor:YUITest.Reporter,addField:function(e,t){this._fields[e]=t},clearFields:function(){this._fields=new Object},destroy:function(){this._form&&(this._form.parentNode.removeChild(this._form),this._form=null),this._iframe&&(this._iframe.parentNode.removeChild(this._iframe),this._iframe=null),this._fields=null},report:function(e){if(!this._form){this._form=document.createElement("form"),this._form.method="post",this._form.style.visibility="hidden",this._form.style.position="absolute",this._form.style.top=0,document.body.appendChild(this._form);try{this._iframe=document.createElement('<iframe name="yuiTestTarget" />')}catch(t){this._iframe=document.createElement("iframe"),this._iframe.name="yuiTestTarget"}this._iframe.src="javascript:false",this._iframe.style.visibility="hidden",this._iframe.style.position="absolute",this._iframe.style.top=0,document.body.appendChild(this._iframe),this._form.target="yuiTestTarget"}this._form.action=this.url;while(this._form.hasChildNodes())this._form.removeChild(this._form.lastChild);this._fields.results=this.format(e),this._fields.useragent=navigator.userAgent,this._fields.timestamp=(new Date).toLocaleString();for(var n in this._fields){var r=this._fields[n];if(this._fields.hasOwnProperty(n)&&typeof r!="function"){var i=document.createElement("input");i.type="hidden",i.name=n,i.value=r,this._form.appendChild(i)}}delete this._fields.results,delete this._fields.useragent,delete this._fields.timestamp,arguments[1]!==!1&&this._form.submit()}},YUITest.TestRunner=function(){function e(e,t){if(!t.length)return!0;if(e)for(var n=0,r=e.length;n<r;n++)if(t.indexOf(","+e[n]+",")>-1)return!0;return!1}function t(e){this.testObject=e,this.firstChild=null,this.lastChild=null,this.parent=null,this.next=null,this.results=new YUITest.Results,e instanceof YUITest.TestSuite?(this.results.type="testsuite",this.results.name=e.name):e instanceof YUITest.TestCase&&(this.results.type="testcase",this.results.name=e.name)}function n(){YUITest.EventTarget.call(this),this.masterSuite=new YUITest.TestSuite(YUITest.guid("testSuite_")),this._cur=null,this._root=null,this._log=!0,this._waiting=!1,this._running=!1,this._lastResults=null,this._context=null,this._groups=""}return t.prototype={appendChild:function(e){var n=new t(e);return this.firstChild===null?this.firstChild=this.lastChild=n:(this.lastChild.next=n,this.lastChild=n),n.parent=this,n}},n.prototype=YUITest.Util.mix(new YUITest.EventTarget,{_ignoreEmpty:!1,constructor:YUITest.TestRunner,TEST_CASE_BEGIN_EVENT:"testcasebegin",TEST_CASE_COMPLETE_EVENT:"testcasecomplete",TEST_SUITE_BEGIN_EVENT:"testsuitebegin",TEST_SUITE_COMPLETE_EVENT:"testsuitecomplete",TEST_PASS_EVENT:"pass",TEST_FAIL_EVENT:"fail",ERROR_EVENT:"error",TEST_IGNORE_EVENT:"ignore",COMPLETE_EVENT:"complete",BEGIN_EVENT:"begin",_addTestCaseToTestTree:function(e,t){var n=e.appendChild(t),r,i;for(r in t)(r.indexOf("test")===0||r.indexOf(" ")>-1)&&typeof t[r]=="function"&&n.appendChild(r)},_addTestSuiteToTestTree:function(e,t){var n=e.appendChild(t);for(var r=0;r<t.items.length;r++)t.items[r]instanceof YUITest.TestSuite?this._addTestSuiteToTestTree(n,t.items[r]):t.items[r]instanceof YUITest.TestCase&&this._addTestCaseToTestTree(n,t.items[r])},_buildTestTree:function(){this._root=new t(this.masterSuite);for(var e=0;e<this.masterSuite.items.length;e++)this.masterSuite.items[e]instanceof YUITest.TestSuite?this._addTestSuiteToTestTree(this._root,this.masterSuite.items[e]):this.masterSuite.items[e]instanceof YUITest.TestCase&&this._addTestCaseToTestTree(this._root,this.masterSuite.items[e])},_handleTestObjectComplete:function(e){var t;e&&typeof e.testObject=="object"&&(t=e.parent,t&&(t.results.include(e.results),t.results[e.testObject.name]=e.results),e.testObject instanceof YUITest.TestSuite?(this._execNonTestMethod(e,"tearDown",!1),e.results.duration=new Date-e._start,this.fire({type:this.TEST_SUITE_COMPLETE_EVENT,testSuite:e.testObject,results:e.results})):e.testObject instanceof YUITest.TestCase&&(this._execNonTestMethod(e,"destroy",!1),e.results.duration=new Date-e._start,this.fire({type:this.TEST_CASE_COMPLETE_EVENT,testCase:e.testObject,results:e.results})))},_next:function(){if(this._cur===null)this._cur=this._root;else if(this._cur.firstChild)this._cur=this._cur.firstChild;else if(this._cur.next)this._cur=this._cur.next;else{while(this._cur&&!this._cur.next&&this._cur!==this._root)this._handleTestObjectComplete(this._cur),this._cur=this._cur.parent;this._handleTestObjectComplete(this._cur),this._cur==this._root?(this._cur.results.type="report",this._cur.results.timestamp=(new Date).toLocaleString(),this._cur.results.duration=new Date-this._cur._start,this._lastResults=this._cur.results,this._running=!1,this.fire({type:this.COMPLETE_EVENT,results:this._lastResults}),this._cur=null):this._cur&&(this._cur=this._cur.next)}return this._cur},_execNonTestMethod:function(e,t,n){var r=e.testObject,i={type:this.ERROR_EVENT};try{if(n&&r["async:"+t])return r["async:"+t](this._context),!0;r[t](this._context)}catch(s){e.results.errors++,i.error=s,i.methodName=t,r instanceof YUITest.TestCase?i.testCase=r:i.testSuite=testSuite,this.fire(i)}return!1},_run:function(){var e=!1,t=this._next();if(t!==null){this._running=!0,this._lastResult=null;var n=t.testObject;if(typeof n=="object"&&n!==null){if(n instanceof YUITest.TestSuite)this.fire({type:this.TEST_SUITE_BEGIN_EVENT,testSuite:n}),t._start=new Date,this._execNonTestMethod(t,"setUp",!1);else if(n instanceof YUITest.TestCase){this.fire({type:this.TEST_CASE_BEGIN_EVENT,testCase:n}),t._start=new Date;if(this._execNonTestMethod(t,"init",!0))return}typeof setTimeout!="undefined"?setTimeout(function(){YUITest.TestRunner._run()},0):this._run()}else this._runTest(t)}},_resumeTest:function(e){var t=this._cur;this._waiting=!1;if(!t)return;var n=t.testObject,r=t.parent.testObject;r.__yui_wait&&(clearTimeout(r.__yui_wait),delete r.__yui_wait);var i=n.indexOf("fail:")===0||(r._should.fail||{})[n],s=(r._should.error||{})[n],o=!1,u=null;try{e.call(r,this._context);if(YUITest.Assert._getCount()==0&&!this._ignoreEmpty)throw new YUITest.AssertionError("Test has no asserts.");i?(u=new YUITest.ShouldFail,o=!0):s&&(u=new YUITest.ShouldError,o=!0)}catch(a){r.__yui_wait&&(clearTimeout(r.__yui_wait),delete r.__yui_wait);if(a instanceof YUITest.AssertionError)i||(u=a,o=!0);else{if(a instanceof YUITest.Wait){if(typeof a.segment=="function"&&typeof a.delay=="number"){if(typeof setTimeout=="undefined")throw new Error("Asynchronous tests not supported in this environment.");r.__yui_wait=setTimeout(function(){YUITest.TestRunner._resumeTest(a.segment)},a.delay),this._waiting=!0}return}s?typeof s=="string"?a.message!=s&&(u=new YUITest.UnexpectedError(a),o=!0):typeof s=="function"?a instanceof s||(u=new YUITest.UnexpectedError(a),o=!0):typeof s=="object"&&s!==null&&(!(a instanceof s.constructor)||a.message!=s.message)&&(u=new YUITest.UnexpectedError(a),o=!0):(u=new YUITest.UnexpectedError(a),o=!0)}}o?this.fire({type:this.TEST_FAIL_EVENT,testCase:r,testName:n,error:u}):this.fire({type:this.TEST_PASS_EVENT,testCase:r,testName:n}),this._execNonTestMethod(t.parent,"tearDown",!1),YUITest.Assert._reset();var f=new Date-t._start;t.parent.results[n]={result:o?"fail":"pass",message:u?u.getMessage():"Test passed",type:"test",name:n,duration:f},o?t.parent.results.failed++:t.parent.results.passed++,t.parent.results.total++,typeof setTimeout!="undefined"?setTimeout(function(){YUITest.TestRunner._run()},0):this._run()},_handleError:function(e){if(!this._waiting)throw e;this._resumeTest(function(){throw e})},_runTest:function(t){var n=t.testObject,r=t.parent.testObject,i=r[n],s=n.indexOf("ignore:")===0||!e(r.groups,this._groups)||(r._should.ignore||{})[n];s?(t.parent.results[n]={result:"ignore",message:"Test ignored",type:"test",name:n.indexOf("ignore:")===0?n.substring(7):n},t.parent.results.ignored++,t.parent.results.total++,this.fire({type:this.TEST_IGNORE_EVENT,testCase:r,testName:n}),typeof setTimeout!="undefined"?setTimeout(function(){YUITest.TestRunner._run()},0):this._run()):(t._start=new Date,this._execNonTestMethod(t.parent,"setUp",!1),this._resumeTest(i))},getName:function(){return this.masterSuite.name},setName:function(e){this.masterSuite.name=e},add:function(e){return this.masterSuite.add(e),this},clear:function(){this.masterSuite=new YUITest.TestSuite(YUITest.guid("testSuite_"))},isWaiting:function(){return this._waiting},isRunning:function(){return this._running},getResults:function(e){return!this._running&&this._lastResults?typeof e=="function"?e(this._lastResults):this._lastResults:null},getCoverage:function(e){var t=null;return typeof _yuitest_coverage=="object"&&(t=_yuitest_coverage),typeof __coverage__=="object"&&(t=__coverage__),!this._running&&typeof t=="object"?typeof e=="function"?e(t):t:null},callback:function(){var e=arguments,t=this._context,n=this;return function(){for(var r=0;r<arguments.length;r++)t[e[r]]=arguments[r];n._run()}},resume:function(e){if(!this._waiting)throw new Error("resume() called without wait().");this._resumeTest(e||function(){})},run:function(e){e=e||{};var t=YUITest.TestRunner,n=e.oldMode;!n&&this.masterSuite.items.length==1&&this.masterSuite.items[0]instanceof YUITest.TestSuite&&(this.masterSuite=this.masterSuite.items[0]),t._groups=e.groups instanceof Array?","+e.groups.join(",")+",":"",t._buildTestTree(),t._context={},t._root._start=new Date,t.fire(t.BEGIN_EVENT),t._run()}}),new n}(),YUITest.ArrayAssert={_indexOf:function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n<e.length;n++)if(e[n]===t)return n;return-1},_some:function(e,t){if(e.some)return e.some(t);for(var n=0;n<e.length;n++)if(t(e[n]))return!0;return!1},contains:function(e,t,n){YUITest.Assert._increment(),this._indexOf(t,e)==-1&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value "+e+" ("+typeof e+") not found in array ["+t+"]."))},containsItems:function(e,t,n){YUITest.Assert._increment();for(var r=0;r<e.length;r++)this._indexOf(t,e[r])==-1&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value "+e[r]+" ("+typeof e[r]+") not found in array ["+t+"]."))},containsMatch:function(e,t,n){YUITest.Assert._increment();if(typeof e!="function")throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function.");this._some(t,e)||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"No match found in array ["+t+"]."))},doesNotContain:function(e,t,n){YUITest.Assert._increment(),this._indexOf(t,e)>-1&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value found in array ["+t+"]."))},doesNotContainItems:function(e,t,n){YUITest.Assert._increment();for(var r=0;r<e.length;r++)this._indexOf(t,e[r])>-1&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value found in array ["+t+"]."))},doesNotContainMatch:function(e,t,n){YUITest.Assert._increment();if(typeof e!="function")throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function.");this._some(t,e)&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value found in array ["+t+"]."))},indexOf:function(e,t,n,r){YUITest.Assert._increment();for(var i=0;i<t.length;i++)if(t[i]===e){n!=i&&YUITest.Assert.fail(YUITest.Assert._formatMessage(r,"Value exists at index "+i+" but should be at index "+n+"."));return}YUITest.Assert.fail(YUITest.Assert._formatMessage(r,"Value doesn't exist in array ["+t+"]."))},itemsAreEqual:function(e,t,n){YUITest.Assert._increment(),(typeof e!="object"||typeof t!="object")&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Value should be an array.")),e.length!=t.length&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Array should have a length of "+e.length+" but has a length of "+t.length+"."));for(var r=0;r<e.length;r++)if(e[r]!=t[r])throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Values in position "+r+" are not equal."),e[r],t[r])},itemsAreEquivalent:function(e,t,n,r){YUITest.Assert._increment();if(typeof n!="function")throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function.");e.length!=t.length&&YUITest.Assert.fail(YUITest.Assert._formatMessage(r,"Array should have a length of "+e.length+" but has a length of "+t.length));for(var i=0;i<e.length;i++)if(!n(e[i],t[i]))throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(r,"Values in position "+i+" are not equivalent."),e[i],t[i])},isEmpty:function(e,t){YUITest.Assert._increment(),e.length>0&&YUITest.Assert.fail(YUITest.Assert._formatMessage(t,"Array should be empty."))},isNotEmpty:function(e,t){YUITest.Assert._increment(),e.length===0&&YUITest.Assert.fail(YUITest.Assert._formatMessage(t,"Array should not be empty."))},itemsAreSame:function(e,t,n){YUITest.Assert._increment(),e.length!=t.length&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Array should have a length of "+e.length+" but has a length of "+t.length));for(var r=0;r<e.length;r++)if(e[r]!==t[r])throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Values in position "+r+" are not the same."),e[r],t[r])},lastIndexOf:function(e,t,n,r){for(var i=t.length;i>=0;i--)if(t[i]===e){n!=i&&YUITest.Assert.fail(YUITest.Assert._formatMessage(r,"Value exists at index "+i+" but should be at index "+n+"."));return}YUITest.Assert.fail(YUITest.Assert._formatMessage(r,"Value doesn't exist in array."))}},YUITest.Assert={_asserts:0,_formatMessage:function(e,t){return typeof e=="string"&&e.length>0?e.replace("{message}",t):t},_getCount:function(){return this._asserts},_increment:function(){this._asserts++},_reset:function(){this._asserts=0},fail:function(e){throw new YUITest.AssertionError(YUITest.Assert._formatMessage(e,"Test force-failed."))},pass:function(e){YUITest.Assert._increment()},areEqual:function(e,t,n){YUITest.Assert._increment();if(e!=t)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Values should be equal."),e,t)},areNotEqual:function(e,t,n){YUITest.Assert._increment();if(e==t)throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(n,"Values should not be equal."),e)},areNotSame:function(e,t,n){YUITest.Assert._increment();if(e===t)throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(n,"Values should not be the same."),e)},areSame:function(e,t,n){YUITest.Assert._increment();if(e!==t)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Values should be the same."),e,t)},isFalse:function(e,t){YUITest.Assert._increment();if(!1!==e)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(t,"Value should be false."),!1,e)},isTrue:function(e,t){YUITest.Assert._increment();if(!0!==e)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(t,"Value should be true."),!0,e)},isNaN:function(e,t){YUITest.Assert._increment();if(!isNaN(e))throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(t,"Value should be NaN."),NaN,e)},isNotNaN:function(e,t){YUITest.Assert._increment();if(isNaN(e))throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Values should not be NaN."),NaN)},isNotNull:function(e,t){YUITest.Assert._increment();if(e===null)throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Values should not be null."),null)},isNotUndefined:function(e,t){YUITest.Assert._increment();if(typeof e=="undefined")throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should not be undefined."),undefined)},isNull:function(e,t){YUITest.Assert._increment();if(e!==null)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(t,"Value should be null."),null,e)},isUndefined:function(e,t){YUITest.Assert._increment();if(typeof e!="undefined")throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(t,"Value should be undefined."),undefined,e)},isArray:function(e,t){YUITest.Assert._increment();var n=!1;Array.isArray?n=!Array.isArray(e):n=Object.prototype.toString.call(e)!="[object Array]";if(n)throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be an array."),e)},isBoolean:function(e,t){YUITest.Assert._increment();if(typeof e!="boolean")throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be a Boolean."),e)},isFunction:function(e,t){YUITest.Assert._increment();if(!(e instanceof Function))throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be a function."),e)},isInstanceOf:function(e,t,n){YUITest.Assert._increment();if(!(t instanceof e))throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Value isn't an instance of expected type."),e,t)},isNumber:function(e,t){YUITest.Assert._increment();if(typeof e!="number")throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be a number."),e)},isObject:function(e,t){YUITest.Assert._increment();if(!e||typeof e!="object"&&typeof e!="function")throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be an object."),e)},isString:function(e,t){YUITest.Assert._increment();if(typeof e!="string")throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(t,"Value should be a string."),e)},isTypeOf:function(e,t,n){YUITest.Assert._increment();if(typeof t!=e)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Value should be of type "+e+"."),e,typeof t)},throwsError:function(e,t,n){YUITest.Assert._increment();var r=!1;try{t()}catch(i){if(typeof e=="string")i.message!=e&&(r=!0);else if(typeof e=="function")i instanceof e||(r=!0);else if(typeof e=="object"&&e!==null){if(!(i instanceof e.constructor)||i.message!=e.message)r=!0}else r=!0;if(r)throw new YUITest.UnexpectedError(i);return}throw new YUITest.AssertionError(YUITest.Assert._formatMessage(n,"Error should have been thrown."))}},YUITest.AssertionError=function(e){this.message=e,this.name="Assert Error"},YUITest.AssertionError.prototype={constructor:YUITest.AssertionError,getMessage:function(){return this.message},toString:function(){return this.name+": "+this.getMessage()}},YUITest.ComparisonFailure=function(e,t,n){YUITest.AssertionError.call(this,e),this.expected=t,this.actual=n,this.name="ComparisonFailure"},YUITest.ComparisonFailure.prototype=new YUITest.AssertionError,YUITest.ComparisonFailure.prototype.constructor=YUITest.ComparisonFailure,YUITest.ComparisonFailure.prototype.getMessage=function(){return this.message+"\nExpected: "+this.expected+" ("+typeof this.expected+")"+"\nActual: "+this.actual+" ("+typeof this.actual+")"},YUITest.CoverageFormat={JSON:function(e){return YUITest.Util.JSON.stringify(e)},XdebugJSON:function(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n].lines);return YUITest.Util.JSON.stringify(e)}},YUITest.DateAssert={datesAreEqual:function(e,t,n){YUITest.Assert._increment();if(!(e instanceof Date&&t instanceof Date))throw new TypeError("YUITest.DateAssert.datesAreEqual(): Expected and actual values must be Date objects.");var r="";e.getFullYear()!=t.getFullYear()&&(r="Years should be equal."),e.getMonth()!=t.getMonth()&&(r="Months should be equal."),e.getDate()!=t.getDate()&&(r="Days of month should be equal.");if(r.length)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,r),e,t)},timesAreEqual:function(e,t,n){YUITest.Assert._increment();if(!(e instanceof Date&&t instanceof Date))throw new TypeError("YUITest.DateAssert.timesAreEqual(): Expected and actual values must be Date objects.");var r="";e.getHours()!=t.getHours()&&(r="Hours should be equal."),e.getMinutes()!=t.getMinutes()&&(r="Minutes should be equal."),e.getSeconds()!=t.getSeconds()&&(r="Seconds should be equal.");if(r.length)throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,r),e,t)}},YUITest.Mock=function(e){e=e||{};var t,n;try{function r(){}r.prototype=e,t=new r}catch(i){t={}}for(n in e)e.hasOwnProperty(n)&&typeof e[n]=="function"&&(t[n]=function(e){return function(){YUITest.Assert.fail("Method "+e+"() was called but was not expected to be.")}}(n));return t},YUITest.Mock.expect=function(e,t){e.__expectations||(e.__expectations={});if(t.method){var n=t.method,r=t.args||[],i=t.returns,s=typeof t.callCount=="number"?t.callCount:1,o=t.error,u=t.run||function(){},a,f;e.__expectations[n]=t,t.callCount=s,t.actualCallCount=0;for(f=0;f<r.length;f++)r[f]instanceof YUITest.Mock.Value||(r[f]=YUITest.Mock.Value(YUITest.Assert.areSame,[r[f]],"Argument "+f+" of "+n+"() is incorrect."));s>0?e[n]=function(){try{t.actualCallCount++,YUITest.Assert.areEqual(r.length,arguments.length,"Method "+n+"() passed incorrect number of arguments.");for(var e=0,s=r.length;e<s;e++)r[e].verify(arguments[e]);a=u.apply(this,arguments);if(o)throw o}catch(f){YUITest.TestRunner._handleError(f)}return t.hasOwnProperty("returns")?i:a}:e[n]=function(){try{YUITest.Assert.fail("Method "+n+"() should not have been called.")}catch(e){YUITest.TestRunner._handleError(e)}}}else t.property&&(e.__expectations[t.property]=t)},YUITest.Mock.verify=function(e){try{for(var t in e.__expectations)if(e.__expectations.hasOwnProperty(t)){var n=e.__expectations[t];n.method?YUITest.Assert.areEqual(n.callCount,n.actualCallCount,"Method "+n.method+"() wasn't called the expected number of times."):n.property&&YUITest.Assert.areEqual(n.value,e[n.property],"Property "+n.property+" wasn't set to the correct value.")}}catch(r){YUITest.TestRunner._handleError(r)}},YUITest.Mock.Value=function(e,t,n){if(!(this instanceof YUITest.Mock.Value))return new YUITest.Mock.Value(e,t,n);this.verify=function(r){var i=[].concat(t||[]);i.push(r),i.push(n),e.apply(null,i)}},YUITest.Mock.Value.Any=YUITest.Mock.Value(function(){}),YUITest.Mock.Value.Boolean=YUITest.Mock.Value(YUITest.Assert.isBoolean),YUITest.Mock.Value.Number=YUITest.Mock.Value(YUITest.Assert.isNumber),YUITest.Mock.Value.String=YUITest.Mock.Value(YUITest.Assert.isString),YUITest.Mock.Value.Object=YUITest.Mock.Value(YUITest.Assert.isObject),YUITest.Mock.Value.Function=YUITest.Mock.Value(YUITest.Assert.isFunction),YUITest.ObjectAssert={areEqual:function(e,t,n){YUITest.Assert._increment();var r=YUITest.Object.keys(e),i=YUITest.Object.keys(t);r.length!=i.length&&YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Object should have "+r.length+" keys but has "+i.length));for(var s in e)if(e.hasOwnProperty(s)&&e[s]!=t[s])throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(n,"Values should be equal for property "+s),e[s],t[s])},hasKey:function(e,t,n){YUITest.ObjectAssert.ownsOrInheritsKey(e,t,n)},hasKeys:function(e,t,n){YUITest.ObjectAssert.ownsOrInheritsKeys(e,t,n)},inheritsKey:function(e,t,n){YUITest.Assert._increment(),e in t&&!t.hasOwnProperty(e)||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e+"' not found on object instance."))},inheritsKeys:function(e,t,n){YUITest.Assert._increment();for(var r=0;r<e.length;r++)propertyName in t&&!t.hasOwnProperty(e[r])||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e[r]+"' not found on object instance."))},ownsKey:function(e,t,n){YUITest.Assert._increment(),t.hasOwnProperty(e)||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e+"' not found on object instance."))},ownsKeys:function(e,t,n){YUITest.Assert._increment();for(var r=0;r<e.length;r++)t.hasOwnProperty(e[r])||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e[r]+"' not found on object instance."))},ownsNoKeys:function(e,t){YUITest.Assert._increment();var n=0,r;for(r in e)e.hasOwnProperty(r)&&n++;n!==0&&YUITest.Assert.fail(YUITest.Assert._formatMessage(t,"Object owns "+n+" properties but should own none."))},ownsOrInheritsKey:function(e,t,n){YUITest.Assert._increment(),e in t||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e+"' not found on object."))},ownsOrInheritsKeys:function(e,t,n){YUITest.Assert._increment();for(var r=0;r<e.length;r++)e[r]in t||YUITest.Assert.fail(YUITest.Assert._formatMessage(n,"Property '"+e[r]+"' not found on object."))}},YUITest.Results=function(e){this.name=e,this.passed=0,this.failed=0,this.errors=0,this.ignored=0,this.total=0,this.duration=0},YUITest.Results.prototype.include=function(e){this.passed+=e.passed,this.failed+=e.failed,this.ignored+=e.ignored,this.total+=e.total,this.errors+=e.errors},YUITest.ShouldError=function(e){YUITest.AssertionError.call(this,e||"This test should have thrown an error but didn't."),this.name="ShouldError"},YUITest.ShouldError.prototype=new YUITest.AssertionError,YUITest.ShouldError.prototype.constructor=YUITest.ShouldError,YUITest.ShouldFail=function(e){YUITest.AssertionError.call(this,e||"This test should fail but didn't."),this.name="ShouldFail"},YUITest.ShouldFail.prototype=new YUITest.AssertionError,YUITest.ShouldFail.prototype.constructor=YUITest.ShouldFail,YUITest.UnexpectedError=function(e){YUITest.AssertionError.call(this,"Unexpected error: "+e.message),this.cause=e,this.name="UnexpectedError",this.stack=e.stack},YUITest.UnexpectedError.prototype=new YUITest.AssertionError,YUITest.UnexpectedError.prototype.constructor=YUITest.UnexpectedError,YUITest.UnexpectedValue=function(e,t){YUITest.AssertionError.call(this,e),this.unexpected=t,this.name="UnexpectedValue"},YUITest.UnexpectedValue.prototype=new YUITest.AssertionError,YUITest.UnexpectedValue.prototype.constructor=YUITest.UnexpectedValue,YUITest.UnexpectedValue.prototype.getMessage=function(){return this.message+"\nUnexpected: "+this.unexpected+" ("+typeof this.unexpected+") "},YUITest.Wait=function(e,t){this.segment=typeof e=="function"?e:null,this.delay=typeof t=="number"?t:0},e.Test=YUITest,e.Object.each(YUITest,function(t,n){var n=n.replace("Test","");e.Test[n]=t})),e.Assert=YUITest.Assert,e.Assert.Error=e.Test.AssertionError,e.Assert.ComparisonFailure=e.Test.ComparisonFailure,e.Assert.UnexpectedValue=e.Test.UnexpectedValue,e.Mock=e.Test.Mock,e.ObjectAssert=e.Test.ObjectAssert,e.ArrayAssert=e.Test.ArrayAssert,e.DateAssert=e.Test.DateAssert,e.Test.ResultsFormat=e.Test.TestFormat;var n=e.Test.ArrayAssert.itemsAreEqual;e.Test.ArrayAssert.itemsAreEqual=function(t,r,i){return n.call(this,e.Array(t),e.Array(r),i)},e.assert=function(t,n){e.Assert._increment();if(!t)throw new e.Assert.Error(e.Assert._formatMessage(n,"Assertion failed."))},e.fail=e.Assert.fail,e.Test.Runner.once=e.Test.Runner.subscribe,e.Test.Runner.disableLogging=function(){e.Test.Runner._log=!1},e.Test.Runner.enableLogging=function(){e.Test.Runner._log=!0},e.Test.Runner._ignoreEmpty=!0,e.Test.Runner._log=!0,e.Test.Runner.on=e.Test.Runner.attach;if(!YUI.YUITest){e.config.win&&(e.config.win.YUITest=YUITest),YUI.YUITest=e.Test;var r=function(t){var n="",r="";switch(t.type){case this.BEGIN_EVENT:n="Testing began at "+(new Date).toString()+".",r="info";break;case this.COMPLETE_EVENT:n=e.Lang.sub("Testing completed at "+(new Date).toString()+".\n"+"Passed:{passed} Failed:{failed} "+"Total:{total} ({ignored} ignored)",t.results),r="info";break;case this.TEST_FAIL_EVENT:n=t.testName+": failed.\n"+t.error.getMessage(),r="fail";break;case this.TEST_IGNORE_EVENT:n=t.testName+": ignored.",r="ignore";break;case this.TEST_PASS_EVENT:n=t.testName+": passed.",r="pass";break;case this.TEST_SUITE_BEGIN_EVENT:n='Test suite "'+t.testSuite.name+'" started.',r="info";break;case this.TEST_SUITE_COMPLETE_EVENT:n=e.Lang.sub('Test suite "'+t.testSuite.name+'" completed'+".\n"+"Passed:{passed} Failed:{failed} "+"Total:{total} ({ignored} ignored)",t.results),r="info";break;case this.TEST_CASE_BEGIN_EVENT:n='Test case "'+t.testCase.name+'" started.',r="info";break;case this.TEST_CASE_COMPLETE_EVENT:n=e.Lang.sub('Test case "'+t.testCase.name+'" completed.\n'+"Passed:{passed} Failed:{failed} "+"Total:{total} ({ignored} ignored)",t.results),r="info";break;default:n="Unexpected event "+t.type,r="info"}e.Test.Runner._log&&e.log(n,r,"TestRunner")},i,s;for(i in e.Test.Runner)s=e.Test.Runner[i],i.indexOf("_EVENT")>-1&&e.Test.Runner.subscribe(s,r)}},"3.7.3",{requires:["event-simulate","event-custom","json-stringify"]});
diff --git a/js/yui3/text-accentfold/text-accentfold-min.js b/js/yui3/text-accentfold/text-accentfold-min.js
new file mode 100644
index 000000000..32de2a134
--- /dev/null
+++ b/js/yui3/text-accentfold/text-accentfold-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("text-accentfold",function(e,t){var n=e.Array,r=e.Text,i=r.Data.AccentFold,s={canFold:function(e){var t;for(t in i)if(i.hasOwnProperty(t)&&e.search(i[t])!==-1)return!0;return!1},compare:function(e,t,n){var r=s.fold(e),i=s.fold(t);return n?!!n(r,i):r===i},filter:function(e,t){return n.filter(e,function(e){return t(s.fold(e))})},fold:function(t){return e.Lang.isArray(t)?n.map(t,s.fold):(t=t.toLowerCase(),e.Object.each(i,function(e,n){t=t.replace(e,n)}),t)}};r.AccentFold=s},"3.7.3",{requires:["array-extras","text-data-accentfold"]});
diff --git a/js/yui3/text-data-accentfold/text-data-accentfold-min.js b/js/yui3/text-data-accentfold/text-data-accentfold-min.js
new file mode 100644
index 000000000..07c6006e0
--- /dev/null
+++ b/js/yui3/text-data-accentfold/text-data-accentfold-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("text-data-accentfold",function(e,t){e.namespace("Text.Data").AccentFold={0:/[\u2070\u2080\u24EA\uFF10]/gi,1:/[\u00B9\u2081\u2460\uFF11]/gi,2:/[\u00B2\u2082\u2461\uFF12]/gi,3:/[\u00B3\u2083\u2462\uFF13]/gi,4:/[\u2074\u2084\u2463\uFF14]/gi,5:/[\u2075\u2085\u2464\uFF15]/gi,6:/[\u2076\u2086\u2465\uFF16]/gi,7:/[\u2077\u2087\u2466\uFF17]/gi,8:/[\u2078\u2088\u2467\uFF18]/gi,9:/[\u2079\u2089\u2468\uFF19]/gi,a:/[\u00AA\u00E0-\u00E5\u0101\u0103\u0105\u01CE\u01DF\u01E1\u01FB\u0201\u0203\u0227\u1D43\u1E01\u1E9A\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u24D0\uFF41]/gi,b:/[\u1D47\u1E03\u1E05\u1E07\u24D1\uFF42]/gi,c:/[\u00E7\u0107\u0109\u010B\u010D\u1D9C\u1E09\u24D2\uFF43]/gi,d:/[\u010F\u1D48\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u217E\u24D3\uFF44]/gi,e:/[\u00E8-\u00EB\u0113\u0115\u0117\u0119\u011B\u0205\u0207\u0229\u1D49\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u2091\u212F\u24D4\uFF45]/gi,f:/[\u1DA0\u1E1F\u24D5\uFF46]/gi,g:/[\u011D\u011F\u0121\u0123\u01E7\u01F5\u1D4D\u1E21\u210A\u24D6\uFF47]/gi,h:/[\u0125\u021F\u02B0\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E96\u210E\u24D7\uFF48]/gi,i:/[\u00EC-\u00EF\u0129\u012B\u012D\u012F\u0133\u01D0\u0209\u020B\u1D62\u1E2D\u1E2F\u1EC9\u1ECB\u2071\u2139\u2170\u24D8\uFF49]/gi,j:/[\u0135\u01F0\u02B2\u24D9\u2C7C\uFF4A]/gi,k:/[\u0137\u01E9\u1D4F\u1E31\u1E33\u1E35\u24DA\uFF4B]/gi,l:/[\u013A\u013C\u013E\u0140\u01C9\u02E1\u1E37\u1E39\u1E3B\u1E3D\u2113\u217C\u24DB\uFF4C]/gi,m:/[\u1D50\u1E3F\u1E41\u1E43\u217F\u24DC\uFF4D]/gi,n:/[\u00F1\u0144\u0146\u0148\u01F9\u1E45\u1E47\u1E49\u1E4B\u207F\u24DD\uFF4E]/gi,o:/[\u00BA\u00F2-\u00F6\u014D\u014F\u0151\u01A1\u01D2\u01EB\u01ED\u020D\u020F\u022B\u022D\u022F\u0231\u1D52\u1E4D\u1E4F\u1E51\u1E53\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u2092\u2134\u24DE\uFF4F]/gi,p:/[\u1D56\u1E55\u1E57\u24DF\uFF50]/gi,q:/[\u02A0\u24E0\uFF51]/gi,r:/[\u0155\u0157\u0159\u0211\u0213\u02B3\u1D63\u1E59\u1E5B\u1E5D\u1E5F\u24E1\uFF52]/gi,s:/[\u015B\u015D\u015F\u0161\u017F\u0219\u02E2\u1E61\u1E63\u1E65\u1E67\u1E69\u1E9B\u24E2\uFF53]/gi,t:/[\u0163\u0165\u021B\u1D57\u1E6B\u1E6D\u1E6F\u1E71\u1E97\u24E3\uFF54]/gi,u:/[\u00F9-\u00FC\u0169\u016B\u016D\u016F\u0171\u0173\u01B0\u01D4\u01D6\u01D8\u01DA\u01DC\u0215\u0217\u1D58\u1D64\u1E73\u1E75\u1E77\u1E79\u1E7B\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u24E4\uFF55]/gi,v:/[\u1D5B\u1D65\u1E7D\u1E7F\u2174\u24E5\uFF56]/gi,w:/[\u0175\u02B7\u1E81\u1E83\u1E85\u1E87\u1E89\u1E98\u24E6\uFF57]/gi,x:/[\u02E3\u1E8B\u1E8D\u2093\u2179\u24E7\uFF58]/gi,y:/[\u00FD\u00FF\u0177\u0233\u02B8\u1E8F\u1E99\u1EF3\u1EF5\u1EF7\u1EF9\u24E8\uFF59]/gi,z:/[\u017A\u017C\u017E\u1DBB\u1E91\u1E93\u1E95\u24E9\uFF5A]/gi}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/text-data-wordbreak/text-data-wordbreak-min.js b/js/yui3/text-data-wordbreak/text-data-wordbreak-min.js
new file mode 100644
index 000000000..ca5c90994
--- /dev/null
+++ b/js/yui3/text-data-wordbreak/text-data-wordbreak-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("text-data-wordbreak",function(e,t){e.namespace("Text.Data").WordBreak={aletter:"[A-Za-z\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f3\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bc0-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u24b6-\u24e9\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u303b\u303c\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790\ua791\ua7a0-\ua7a9\ua7fa-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]",midnumlet:"['\\.\u2018\u2019\u2024\ufe52\uff07\uff0e]",midletter:"[:\u00b7\u00b7\u05f4\u2027\ufe13\ufe55\uff1a]",midnum:"[,;;\u0589\u060c\u060d\u066c\u07f8\u2044\ufe10\ufe14\ufe50\ufe54\uff0c\uff1b]",numeric:"[0-9\u0660-\u0669\u066b\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9]",cr:"\\r",lf:"\\n",newline:"[ \f\u0085\u2028\u2029]",extend:"[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f\u109a-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b6-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u192b\u1930-\u193b\u19b0-\u19c0\u19c8\u19c9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f\u1b00-\u1b04\u1b34-\u1b44\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1baa\u1be6-\u1bf3\u1c24-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe3-\uabea\uabec\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]",format:"[\u00ad\u0600-\u0603\u06dd\u070f\u17b4\u17b5\u200e\u200f\u202a-\u202e\u2060-\u2064\u206a-\u206f\ufeff\ufff9-\ufffb]",katakana:"[\u3031-\u3035\u309b\u309c\u30a0-\u30fa\u30fc-\u30ff\u31f0-\u31ff\u32d0-\u32fe\u3300-\u3357\uff66-\uff9d]",extendnumlet:"[_\u203f\u2040\u2054\ufe33\ufe34\ufe4d-\ufe4f\uff3f]",punctuation:"[!-#%-*,-\\/:;?@\\[-\\]_{}\u00a1\u00ab\u00b7\u00bb\u00bf;\u00b7\u055a-\u055f\u0589\u058a\u05be\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1361-\u1368\u1400\u166d\u166e\u169b\u169c\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cd3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205e\u207d\u207e\u208d\u208e\u3008\u3009\u2768-\u2775\u27c5\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc\u29fd\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e2e\u2e30\u2e31\u3001-\u3003\u3008-\u3011\u3014-\u301f\u3030\u303d\u30a0\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uabeb\ufd3e\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a\uff1b\uff1f\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65]"}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/text-wordbreak/text-wordbreak-min.js b/js/yui3/text-wordbreak/text-wordbreak-min.js
new file mode 100644
index 000000000..57e1704d8
--- /dev/null
+++ b/js/yui3/text-wordbreak/text-wordbreak-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("text-wordbreak",function(e,t){var n=e.Text,r=n.Data.WordBreak,i=0,s=1,o=2,u=3,a=4,f=5,l=6,c=7,h=8,p=9,d=10,v=11,m=12,g=[new RegExp(r.aletter),new RegExp(r.midnumlet),new RegExp(r.midletter),new RegExp(r.midnum),new RegExp(r.numeric),new RegExp(r.cr),new RegExp(r.lf),new RegExp(r.newline),new RegExp(r.extend),new RegExp(r.format),new RegExp(r.katakana),new RegExp(r.extendnumlet)],y="",b=new RegExp("^"+r.punctuation+"$"),w=/\s/,E={getWords:function(e,t){var n=0,r=E._classify(e),i=r.length,s=[],o=[],u,a,f;t||(t={}),t.ignoreCase&&(e=e.toLowerCase()),a=t.includePunctuation,f=t.includeWhitespace;for(;n<i;++n)u=e.charAt(n),s.push(u),E._isWordBoundary(r,n)&&(s=s.join(y),s&&(f||!w.test(s))&&(a||!b.test(s))&&o.push(s),s=[]);return o},getUniqueWords:function(t,n){return e.Array.unique(E.getWords(t,n))},isWordBoundary:function(e,t){return E._isWordBoundary(E._classify(e),t)},_classify:function(e){var t,n=[],r=0,i,s,o=e.length,u=g.length,a;for(;r<o;++r){t=e.charAt(r),a=m;for(i=0;i<u;++i){s=g[i];if(s&&s.test(t)){a=i;break}}n.push(a)}return n},_isWordBoundary:function(e,t){var n,r=e[t],m=e[t+1],g;return t<0||t>e.length-1&&t!==0?!1:r===i&&m===i?!1:(g=e[t+2],r!==i||m!==o&&m!==s||g!==i?(n=e[t-1],r!==o&&r!==s||m!==i||n!==i?r!==a&&r!==i||m!==a&&m!==i?r!==u&&r!==s||m!==a||n!==a?r!==a||m!==u&&m!==s||g!==a?r===h||r===p||n===h||n===p||m===h||m===p?!1:r===f&&m===l?!1:r===c||r===f||r===l?!0:m===c||m===f||m===l?!0:r===d&&m===d?!1:m!==v||r!==i&&r!==a&&r!==d&&r!==v?r!==v||m!==i&&m!==a&&m!==d?!0:!1:!1:!1:!1:!1:!1):!1)}};n.WordBreak=E},"3.7.3",{requires:["array-extras","text-data-wordbreak"]});
diff --git a/js/yui3/transition-timer/transition-timer-min.js b/js/yui3/transition-timer/transition-timer-min.js
new file mode 100644
index 000000000..fad30b295
--- /dev/null
+++ b/js/yui3/transition-timer/transition-timer-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("transition-timer",function(e,t){var n=e.Transition;e.mix(n.prototype,{_start:function(){n.useNative?this._runNative():this._runTimer()},_runTimer:function(){var t=this;t._initAttrs(),n._running[e.stamp(t)]=t,t._startTime=new Date,n._startTimer()},_endTimer:function(){var t=this;delete n._running[e.stamp(t)],t._startTime=null},_runFrame:function(){var e=new Date-this._startTime;this._runAttrs(e)},_runAttrs:function(t){var r=this,i=r._node,s=r._config,o=e.stamp(i),u=n._nodeAttrs[o],a=n.behaviors,f=!1,l=!1,c,h,p,d,v,m,g,y,b;for(h in u)if((p=u[h])&&p.transition===r){g=p.duration,m=p.delay,v=(t-m)/1e3,y=t,c={type:"propertyEnd",propertyName:h,config:s,elapsedTime:v},d=b in a&&"set"in a[b]?a[b].set:n.DEFAULT_SETTER,f=y>=g,y>g&&(y=g);if(!m||t>=m)d(r,h,p.from,p.to,y-m,g-m,p.easing,p.unit),f&&(delete u[h],r._count--,s[h]&&s[h].on&&s[h].on.end&&s[h].on.end.call(e.one(i),c),!l&&r._count<=0&&(l=!0,r._end(v),r._endTimer()))}},_initAttrs:function(){var t=this,r=n.behaviors,i=e.stamp(t._node),s=n._nodeAttrs[i],o,u,a,f,l,c,h,p,d,v,m;for(c in s)(o=s[c])&&o.transition===t&&(u=o.duration*1e3,a=o.delay*1e3,f=o.easing,l=o.value,c in t._node.style||c in e.DOM.CUSTOM_STYLES?(v=c in r&&"get"in r[c]?r[c].get(t,c):n.DEFAULT_GETTER(t,c),p=n.RE_UNITS.exec(v),h=n.RE_UNITS.exec(l),v=p?p[1]:v,m=h?h[1]:l,d=h?h[2]:p?p[2]:"",!d&&n.RE_DEFAULT_UNIT.test(c)&&(d=n.DEFAULT_UNIT),typeof f=="string"&&(f.indexOf("cubic-bezier")>-1?f=f.substring(13,f.length-1).split(","):n.easings[f]&&(f=n.easings[f])),o.from=Number(v),o.to=Number(m),o.unit=d,o.easing=f,o.duration=u+a,o.delay=a):(delete s[c],t._count--))},destroy:function(){this.detachAll(),this._node=null}},!0),e.mix(e.Transition,{_runtimeAttrs:{},RE_DEFAULT_UNIT:/^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,DEFAULT_UNIT:"px",intervalTime:20,behaviors:{left:{get:function(t,n){return e.DOM._getAttrOffset(t._node,n)}}},DEFAULT_SETTER:function(t,r,i,s,o,u,a,f){i=Number(i),s=Number(s);var l=t._node,c=n.cubicBezier(a,o/u);c=i+c[0]*(s-i);if(l){if(r in l.style||r in e.DOM.CUSTOM_STYLES)f=f||"",e.DOM.setStyle(l,r,c+f)}else t._end()},DEFAULT_GETTER:function(t,n){var r=t._node,i="";if(n in r.style||n in e.DOM.CUSTOM_STYLES)i=e.DOM.getComputedStyle(r,n);return i},_startTimer:function(){n._timer||(n._timer=setInterval(n._runFrame,n.intervalTime))},_stopTimer:function(){clearInterval(n._timer),n._timer=null},_runFrame:function(){var e=!0,t;for(t in n._running)n._running[t]._runFrame&&(e=!1,n._running[t]._runFrame());e&&n._stopTimer()},cubicBezier:function(e,t){var n=0,r=0,i=e[0],s=e[1],o=e[2],u=e[3],a=1,f=0,l=a-3*o+3*i-n,c=3*o-6*i+3*n,h=3*i-3*n,p=n,d=f-3*u+3*s-r,v=3*u-6*s+3*r,m=3*s-3*r,g=r,y=((l*t+c)*t+h)*t+p,b=((d*t+v)*t+m)*t+g;return[y,b]},easings:{ease:[.25,0,1,.25],linear:[0,0,1,1],"ease-in":[.42,0,1,1],"ease-out":[0,0,.58,1],"ease-in-out":[.42,0,.58,1]},_running:{},_timer:null,RE_UNITS:/^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/},!0),n.behaviors.top=n.behaviors.bottom=n.behaviors.right=n.behaviors.left,e.Transition=n},"3.7.3",{requires:["transition"]});
diff --git a/js/yui3/transition/transition-min.js b/js/yui3/transition/transition-min.js
new file mode 100644
index 000000000..09c067be7
--- /dev/null
+++ b/js/yui3/transition/transition-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("transition",function(e,t){var n="",r="",i=e.config.doc,s="documentElement",o="transition",u="transition",a="transitionProperty",f="transform",l,c,h,p,d,v,m={},g=["Webkit","Moz"],y={Webkit:"webkitTransitionEnd"},b=function(){this.init.apply(this,arguments)};b._toCamel=function(e){return e=e.replace(/-([a-z])/gi,function(e,t){return t.toUpperCase()}),e},b._toHyphen=function(e){return e=e.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g,function(e,t,n,r){var i=(t?"-"+t.toLowerCase():"")+n;return r&&(i+="-"+r.toLowerCase()),i}),e},b.SHOW_TRANSITION="fadeIn",b.HIDE_TRANSITION="fadeOut",b.useNative=!1,"transition"in i[s].style?(b.useNative=!0,b.supported=!0):e.Array.each(g,function(e){var t=e+"Transition";t in i[s].style&&(n=e,r=b._toHyphen(e)+"-",b.useNative=!0,b.supported=!0,b._VENDOR_PREFIX=e)}),n&&(u=n+"Transition",a=n+"TransitionProperty",f=n+"Transform"),l=r+"transition-property",c=r+"transition-duration",h=r+"transition-timing-function",p=r+"transition-delay",d="transitionend",v="on"+n.toLowerCase()+"transitionend",d=y[n]||d,b.fx={},b.toggles={},b._hasEnd={},b._reKeywords=/^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i,e.Node.DOM_EVENTS[d]=1,b.NAME="transition",b.DEFAULT_EASING="ease",b.DEFAULT_DURATION=.5,b.DEFAULT_DELAY=0,b._nodeAttrs={},b.prototype={constructor:b,init:function(e,t){var n=this;return n._node=e,!n._running&&t&&(n._config=t,e._transition=n,n._duration="duration"in t?t.duration:n.constructor.DEFAULT_DURATION,n._delay="delay"in t?t.delay:n.constructor.DEFAULT_DELAY,n._easing=t.easing||n.constructor.DEFAULT_EASING,n._count=0,n._running=!1),n},addProperty:function(t,n){var r=this,i=this._node,s=e.stamp(i),o=e.one(i),u=b._nodeAttrs[s],a,f,l,c,h;u||(u=b._nodeAttrs[s]={}),c=u[t],n&&n.value!==undefined?h=n.value:n!==undefined&&(h=n,n=m),typeof h=="function"&&(h=h.call(o,o)),c&&c.transition&&c.transition!==r&&c.transition._count--,r._count++,l=(typeof n.duration!="undefined"?n.duration:r._duration)||1e-4,u[t]={value:h,duration:l,delay:typeof n.delay!="undefined"?n.delay:r._delay,easing:n.easing||r._easing,transition:r},a=e.DOM.getComputedStyle(i,t),f=typeof h=="string"?a:parseFloat(a),b.useNative&&f===h&&setTimeout(function(){r._onNativeEnd.call(i,{propertyName:t,elapsedTime:l})},l*1e3)},removeProperty:function(t){var n=this,r=b._nodeAttrs[e.stamp(n._node)];r&&r[t]&&(delete r[t],n._count--)},initAttrs:function(t){var n,r=this._node;t.transform&&!t[f]&&(t[f]=t.transform,delete t.transform);for(n in t)t.hasOwnProperty(n)&&!b._reKeywords.test(n)&&(this.addProperty(n,t[n]),r.style[n]===""&&e.DOM.setStyle(r,n,e.DOM.getComputedStyle(r,n)))},run:function(t){var n=this,r=n._node,i=n._config,s={type:"transition:start",config:i};return n._running||(n._running=!0,i.on&&i.on.start&&i.on.start.call(e.one(r),s),n.initAttrs(n._config),n._callback=t,n._start()),n},_start:function(){this._runNative()},_prepDur:function(e){return e=parseFloat(e)*1e3,e+"ms"},_runNative:function(t){var n=this,r=n._node,i=e.stamp(r),s=r.style,o=r.ownerDocument.defaultView.getComputedStyle(r),u=b._nodeAttrs[i],a="",f=o[b._toCamel(l)],v=l+": ",m=c+": ",g=h+": ",y=p+": ",w,E,S;f!=="all"&&(v+=f+",",m+=o[b._toCamel(c)]+",",g+=o[b._toCamel(h)]+",",y+=o[b._toCamel(p)]+",");for(S in u)w=b._toHyphen(S),E=u[S],(E=u[S])&&E.transition===n&&(S in r.style?(m+=n._prepDur(E.duration)+",",y+=n._prepDur(E.delay)+",",g+=E.easing+",",v+=w+",",a+=w+": "+E.value+"; "):this.removeProperty(S));v=v.replace(/,$/,";"),m=m.replace(/,$/,";"),g=g.replace(/,$/,";"),y=y.replace(/,$/,";"),b._hasEnd[i]||(r.addEventListener(d,n._onNativeEnd,""),b._hasEnd[i]=!0),s.cssText+=v+m+g+y+a},_end:function(t){var n=this,r=n._node,i=n._callback,s=n._config,o={type:"transition:end",config:s,elapsedTime:t},u=e.one(r);n._running=!1,n._callback=null,r&&(s.on&&s.on.end?setTimeout(function(){s.on.end.call(u,o),i&&i.call(u,o)},1):i&&setTimeout(function(){i.call(u,o)},1))},_endNative:function(e){var t=this._node,n=t.ownerDocument.defaultView.getComputedStyle(t,"")[b._toCamel(l)];e=b._toHyphen(e),typeof n=="string"&&(n=n.replace(new RegExp("(?:^|,\\s)"+e+",?"),","),n=n.replace(/^,|,$/,""),t.style[u]=n)},_onNativeEnd:function(t){var n=this,r=e.stamp(n),i=t,s=b._toCamel(i.propertyName),o=i.elapsedTime,u=b._nodeAttrs[r],f=u[s],l=f?f.transition:null,c,h;l&&(l.removeProperty(s),l._endNative(s),h=l._config[s],c={type:"propertyEnd",propertyName:s,elapsedTime:o,config:h},h&&h.on&&h.on.end&&h.on.end.call(e.one(n),c),l._count<=0&&(l._end(o),n.style[a]=""))},destroy:function(){var e=this,t=e._node;t&&(t.removeEventListener(d,e._onNativeEnd,!1),e._node=null)}},e.Transition=b,e.TransitionNative=b,e.Node.prototype.transition=function(t,n,r){var i=b._nodeAttrs[e.stamp(this._node)],s=i?i.transition||null:null,o,u;if(typeof t=="string"){typeof n=="function"&&(r=n,n=null),o=b.fx[t];if(n&&typeof n!="boolean"){n=e.clone(n);for(u in o)o.hasOwnProperty(u)&&(u in n||(n[u]=o[u]))}else n=o}else r=n,n=t;return s&&!s._running?s.init(this,n):s=new b(this._node,n),s.run(r),this},e.Node.prototype.show=function(t,n,r){return this._show(),t&&e.Transition&&(typeof t!="string"&&!t.push&&(typeof n=="function"&&(r=n,n=t),t=b.SHOW_TRANSITION),this.transition(t,n,r)),this};var w=function(e,t,n){return function(){t&&t.call(e),n&&n.apply(e._node,arguments)}};e.Node.prototype.hide=function(t,n,r){return t&&e.Transition?(typeof n=="function"&&(r=n,n=null),r=w(this,this._hide,r),typeof t!="string"&&!t.push&&(typeof n=="function"&&(r=n,n=t),t=b.HIDE_TRANSITION),this.transition(t,n,r)):this._hide(),this},e.NodeList.prototype.transition=function(t,n){var r=this._nodes,i=0,s;while(s=r[i++])e.one(s).transition(t,n);return this},e.Node.prototype.toggleView=function(t,n,r){return this._toggles=this._toggles||[],r=arguments[arguments.length-1],typeof t=="boolean"&&(n=t,t=null),t=t||e.Transition.DEFAULT_TOGGLE,typeof n=="undefined"&&t in this._toggles&&(n=!this._toggles[t]),n=n?1:0,n?this._show():r=w(this,this._hide,r),this._toggles[t]=n,this.transition(e.Transition.toggles[t][n],r),this},e.NodeList.prototype.toggleView=function(t,n,r){var i=this._nodes,s=0,o;while(o=i[s++])e.one(o).toggleView(t,n,r);return this},e.mix(b.fx,{fadeOut:{opacity:0,duration:.5,easing:"ease-out"},fadeIn:{opacity:1,duration:.5,easing:"ease-in"},sizeOut:{height:0,width:0,duration:.75,easing:"ease-out"},sizeIn:{height:function(e){return e.get("scrollHeight")+"px"},width:function(e){return e.get("scrollWidth")+"px"},duration:.5,easing:"ease-in",on:{start:function(){var e=this.getStyle("overflow");e!=="hidden"&&(this.setStyle("overflow","hidden"),this._transitionOverflow=e)},end:function(){this._transitionOverflow&&(this.setStyle("overflow",this._transitionOverflow),delete this._transitionOverflow)}}}}),e.mix(b.toggles,{size:["sizeOut","sizeIn"],fade:["fadeOut","fadeIn"]}),b.DEFAULT_TOGGLE="fade"},"3.7.3",{requires:["node-style"]});
diff --git a/js/yui3/uploader-deprecated/assets/uploader.swf b/js/yui3/uploader-deprecated/assets/uploader.swf
new file mode 100644
index 000000000..95b853a7a
--- /dev/null
+++ b/js/yui3/uploader-deprecated/assets/uploader.swf
Binary files differ
diff --git a/js/yui3/uploader-deprecated/uploader-deprecated-min.js b/js/yui3/uploader-deprecated/uploader-deprecated-min.js
new file mode 100644
index 000000000..b4917dae6
--- /dev/null
+++ b/js/yui3/uploader-deprecated/uploader-deprecated-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("uploader-deprecated",function(e){var b=e.Event,c=e.Node;var a=e.Env.cdn+"uploader-deprecated/assets/uploader.swf";function d(f){d.superclass.constructor.apply(this,arguments);if(f.hasOwnProperty("boundingBox")){this.set("boundingBox",f.boundingBox);}if(f.hasOwnProperty("buttonSkin")){this.set("buttonSkin",f.buttonSkin);}if(f.hasOwnProperty("transparent")){this.set("transparent",f.transparent);}if(f.hasOwnProperty("swfURL")){this.set("swfURL",f.swfURL);}}e.extend(d,e.Base,{uploaderswf:null,_id:"",initializer:function(){this._id=e.guid("uploader");var f=c.one(this.get("boundingBox"));var i={version:"10.0.45",fixedAttributes:{allowScriptAccess:"always",allowNetworking:"all",scale:"noscale"},flashVars:{}};if(this.get("buttonSkin")!=""){i.flashVars["buttonSkin"]=this.get("buttonSkin");}if(this.get("transparent")){i.fixedAttributes["wmode"]="transparent";}this.uploaderswf=new e.SWF(f,this.get("swfURL"),i);var h=this.uploaderswf;var g=e.bind(this._relayEvent,this);h.on("swfReady",e.bind(this._initializeUploader,this));h.on("click",g);h.on("fileselect",g);h.on("mousedown",g);h.on("mouseup",g);h.on("mouseleave",g);h.on("mouseenter",g);h.on("uploadcancel",g);h.on("uploadcomplete",g);h.on("uploadcompletedata",g);h.on("uploaderror",g);h.on("uploadprogress",g);h.on("uploadstart",g);},removeFile:function(f){return this.uploaderswf.callSWF("removeFile",[f]);},clearFileList:function(){return this.uploaderswf.callSWF("clearFileList",[]);},upload:function(f,h,j,g,i){if(e.Lang.isArray(f)){return this.uploaderswf.callSWF("uploadThese",[f,h,j,g,i]);}else{if(e.Lang.isString(f)){return this.uploaderswf.callSWF("upload",[f,h,j,g,i]);}}},uploadThese:function(h,g,j,f,i){return this.uploaderswf.callSWF("uploadThese",[h,g,j,f,i]);},uploadAll:function(g,i,f,h){return this.uploaderswf.callSWF("uploadAll",[g,i,f,h]);},cancel:function(f){return this.uploaderswf.callSWF("cancel",[f]);},setAllowLogging:function(f){this.uploaderswf.callSWF("setAllowLogging",[f]);},setAllowMultipleFiles:function(f){this.uploaderswf.callSWF("setAllowMultipleFiles",[f]);},setSimUploadLimit:function(f){this.uploaderswf.callSWF("setSimUploadLimit",[f]);},setFileFilters:function(f){this.uploaderswf.callSWF("setFileFilters",[f]);},enable:function(){this.uploaderswf.callSWF("enable");},disable:function(){this.uploaderswf.callSWF("disable");},_initializeUploader:function(f){this.publish("uploaderReady",{fireOnce:true});this.fire("uploaderReady",{});},_relayEvent:function(f){this.fire(f.type,f);},toString:function(){return"Uploader "+this._id;}},{ATTRS:{log:{value:false,setter:"setAllowLogging"},multiFiles:{value:false,setter:"setAllowMultipleFiles"},simLimit:{value:2,setter:"setSimUploadLimit"},fileFilters:{value:[],setter:"setFileFilters"},boundingBox:{value:null,writeOnce:"initOnly"},buttonSkin:{value:null,writeOnce:"initOnly"},transparent:{value:true,writeOnce:"initOnly"},swfURL:{value:a,writeOnce:"initOnly"}}});e.Uploader=d;},"3.7.3",{requires:["swf","base","node","event-custom"]}); \ No newline at end of file
diff --git a/js/yui3/uploader-flash/assets/uploader-flash-core.css b/js/yui3/uploader-flash/assets/uploader-flash-core.css
new file mode 100644
index 000000000..6f5f82a0a
--- /dev/null
+++ b/js/yui3/uploader-flash/assets/uploader-flash-core.css
@@ -0,0 +1,10 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-uploader-selectfiles-button {
+ width: 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/js/yui3/uploader-flash/uploader-flash-min.js b/js/yui3/uploader-flash/uploader-flash-min.js
new file mode 100644
index 000000000..66c161b26
--- /dev/null
+++ b/js/yui3/uploader-flash/uploader-flash-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("uploader-flash",function(e,t){function u(e){u.superclass.constructor.apply(this,arguments)}var n=e.substitute,r=e.Uploader.Queue,i=e.ClassNameManager.getClassName,s="uploader",o=i(s,"selectfiles-button");e.UploaderFlash=e.extend(u,e.Widget,{_buttonState:"up",_buttonFocus:!1,_swfContainerId:null,_swfReference:null,queue:null,_tabElementBindings:null,initializer:function(){this._swfContainerId=e.guid("uploader"),this._swfReference=null,this.queue=null,this._buttonState="up",this._buttonFocus=null,this._tabElementBindings=null,this._fileList=[],this.publish("fileselect"),this.publish("uploadstart"),this.publish("fileuploadstart"),this.publish("uploadprogress"),this.publish("totaluploadprogress"),this.publish("uploadcomplete"),this.publish("alluploadscomplete"),this.publish("uploaderror"),this.publish("mouseenter"),this.publish("mouseleave"),this.publish("mousedown"),this.publish("mouseup"),this.publish("click")},renderUI:function(){var t=this.get("boundingBox"),r=this.get("contentBox"),i=this.get("selectFilesButton");t.setStyle("position","relative"),i.setStyles({width:"100%",height:"100%"}),r.append(i),r.append(e.Node.create(n(u.FLASH_CONTAINER,{swfContainerId:this._swfContainerId})));var s=e.one("#"+this._swfContainerId),o={version:"10.0.45",fixedAttributes:{wmode:"transparent",allowScriptAccess:"always",allowNetworking:"all",scale:"noscale"}};this._swfReference=new e.SWF(s,this.get("swfURL"),o)},bindUI:function(){this._swfReference.on("swfReady",function(){this._setMultipleFiles(),this._setFileFilters(),this._triggerEnabled(),this._attachTabElements(),this.after("multipleFilesChange",this._setMultipleFiles,this),this.after("fileFiltersChange",this._setFileFilters,this),this.after("enabledChange",this._triggerEnabled,this),this.after("tabElementsChange",this._attachTabElements)},this),this._swfReference.on("fileselect",this._updateFileList,this),this._swfReference.on("mouseenter",function(){this.fire("mouseenter"),this._setButtonClass("hover",!0),this._buttonState=="down"&&this._setButtonClass("active",!0)},this),this._swfReference.on("mouseleave",function(){this.fire("mouseleave"),this._setButtonClass("hover",!1),this._setButtonClass("active",!1)},this),this._swfReference.on("mousedown",function(){this.fire("mousedown"),this._buttonState="down",this._setButtonClass("active",!0)},this),this._swfReference.on("mouseup",function(){this.fire("mouseup"),this._buttonState="up",this._setButtonClass("active",!1)},this),this._swfReference.on("click",function(){this.fire("click"),this._buttonFocus=!0,this._setButtonClass("focus",!0),e.one("body").focus(),this._swfReference._swf.focus()},this)},_attachTabElements:function(t){if(this.get("tabElements")!==null&&this.get("tabElements").from!==null&&this.get("tabElements").to!==null){this._tabElementBindings!==null?(this._tabElementBindings.from.detach(),this._tabElementBindings.to.detach(),this._tabElementBindings.tabback.detach(),this._tabElementBindings.tabforward.detach(),this._tabElementBindings.focus.detach(),this._tabElementBindings.blur.detach()):this._tabElementBindings={};var n=e.one(this.get("tabElements").from),r=e.one(this.get("tabElements").to);this._tabElementBindings.from=n.on("keydown",function(e){e.keyCode==9&&!e.shiftKey&&(e.preventDefault(),this._swfReference._swf.setAttribute("tabindex",0),this._swfReference._swf.setAttribute("role","button"),this._swfReference._swf.setAttribute("aria-label",this.get("selectButtonLabel")),this._swfReference._swf.focus())},this),this._tabElementBindings.to=r.on("keydown",function(e){e.keyCode==9&&e.shiftKey&&(e.preventDefault(),this._swfReference._swf.setAttribute("tabindex",0),this._swfReference._swf.setAttribute("role","button"),this._swfReference._swf.setAttribute("aria-label",this.get("selectButtonLabel")),this._swfReference._swf.focus())},this),this._tabElementBindings.tabback=this._swfReference.on("tabback",function(e){this._swfReference._swf.blur(),setTimeout(function(){n.focus()},30)},this),this._tabElementBindings.tabforward=this._swfReference.on("tabforward",function(e){this._swfReference._swf.blur(),setTimeout(function(){r.focus()},30)},this),this._tabElementBindings.focus=this._swfReference._swf.on("focus",function(e){this._buttonFocus=!0,this._setButtonClass("focus",!0)},this),this._tabElementBindings.blur=this._swfReference._swf.on("blur",function(e){this._buttonFocus=!1,this._setButtonClass("focus",!1)},this)}else this._tabElementBindings!==null&&(this._tabElementBindings.from.detach(),this._tabElementBindings.to.detach(),this._tabElementBindings.tabback.detach(),this._tabElementBindings.tabforward.detach(),this._tabElementBindings.focus.detach(),this._tabElementBindings.blur.detach())},_setButtonClass:function(e,t){t?this.get("selectFilesButton").addClass(this.get("buttonClassNames")[e]):this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[e])},_setFileFilters:function(){this._swfReference&&this.get("fileFilters").length>0&&this._swfReference.callSWF("setFileFilters",[this.get("fileFilters")])},_setMultipleFiles:function(){this._swfReference&&this._swfReference.callSWF("setAllowMultipleFiles",[this.get("multipleFiles")])},_triggerEnabled:function(){this.get("enabled")?(this._swfReference.callSWF("enable"),this._swfReference._swf.setAttribute("aria-disabled","false"),this._setButtonClass("disabled",!1)):(this._swfReference.callSWF("disable"),this._swfReference._swf.setAttribute("aria-disabled","true"),this._setButtonClass("disabled",!0))},_getFileList:function(e){return this._fileList.concat()},_setFileList:function(e){return this._fileList=e.concat(),this._fileList.concat()},_updateFileList:function(t){e.one("body").focus(),this._swfReference._swf.focus();var n=t.fileList,r=[],i=[],s=this._swfReference,o=this.get("fileFilterFunction");e.each(n,function(e){var t={};t.id=e.fileId,t.name=e.fileReference.name,t.size=e.fileReference.size,t.type=e.fileReference.type,t.dateCreated=e.fileReference.creationDate,t.dateModified=e.fileReference.modificationDate,t.uploader=s,r.push(t)}),o?e.each(r,function(t){var n=new e.FileFlash(t);o(n)&&i.push(n)}):e.each(r,function(t){i.push(new e.FileFlash(t))});if(i.length>0){var u=this.get("fileList");this.set("fileList",this.get("appendNewFiles")?u.concat(i):i),this.fire("fileselect",{fileList:i})}},_uploadEventHandler:function(e){switch(e.type){case"file:uploadstart":this.fire("fileuploadstart",e);break;case"file:uploadprogress":this.fire("uploadprogress",e);break;case"uploaderqueue:totaluploadprogress":this.fire("totaluploadprogress",e);break;case"file:uploadcomplete":this.fire("uploadcomplete",e);break;case"uploaderqueue:alluploadscomplete":this.queue=null,this.fire("alluploadscomplete",e);break;case"file:uploaderror":case"uploaderqueue:uploaderror":this.fire("uploaderror",e);break;case"file:uploadcancel":case"uploaderqueue:uploadcancel":this.fire("uploadcancel",e)}},upload:function(t,n,r){var i=n||this.get("uploadURL"),s=r||this.get("postVarsPerFile"),o=t.get("id");s=s.hasOwnProperty(o)?s[o]:s,t instanceof e.FileFlash&&(t.on("uploadstart",this._uploadEventHandler,this),t.on("uploadprogress",this._uploadEventHandler,this),t.on("uploadcomplete",this._uploadEventHandler,this),t.on("uploaderror",this._uploadEventHandler,this),t.on("uploadcancel",this._uploadEventHandler,this),t.startUpload(i,s,this.get("fileFieldName")))},uploadAll:function(e,t){this.uploadThese(this.get("fileList"),e,t)},uploadThese:function(e,t,n){if(!this.queue){var i=t||this.get("uploadURL"),s=n||this.get("postVarsPerFile");this.queue=new r({simUploads:this.get("simLimit"),errorAction:this.get("errorAction"),fileFieldName:this.get("fileFieldName"),fileList:e,uploadURL:i,perFileParameters:s,retryCount:this.get("retryCount")}),this.queue.on("uploadstart",this._uploadEventHandler,this),this.queue.on("uploadprogress",this._uploadEventHandler,this),this.queue.on("totaluploadprogress",this._uploadEventHandler,this),this.queue.on("uploadcomplete",this._uploadEventHandler,this),this.queue.on("alluploadscomplete",this._uploadEventHandler,this),this.queue.on("alluploadscancelled",function(e){this.queue=null},this),this.queue.on("uploaderror",this._uploadEventHandler,this),this.queue.startUpload(),this.fire("uploadstart")}}},{FLASH_CONTAINER:"<div id='{swfContainerId}' style='position:absolute; top:0px; left: 0px; margin: 0; padding: 0; border: 0; width:100%; height:100%'></div>",SELECT_FILES_BUTTON:"<button type='button' class='yui3-button' tabindex='-1'>{selectButtonLabel}</button>",TYPE:"flash",NAME:"uploader",ATTRS:{appendNewFiles:{value:!0},buttonClassNames:{value:{hover:"yui3-button-hover",active:"yui3-button-active",disabled:"yui3-button-disabled",focus:"yui3-button-selected"}},enabled:{value:!0},errorAction:{value:"continue",validator:function(e,t){return e===r.CONTINUE||e===r.STOP||e===r.RESTART_ASAP||e===r.RESTART_AFTER}},fileFilters:{value:[]},fileFilterFunction:{value:null},fileFieldName:{value:"Filedata"},fileList:{value:[],getter:"_getFileList",setter:"_setFileList"},multipleFiles:{value:!1},postVarsPerFile:{value:{}},selectButtonLabel:{value:"Select Files"},selectFilesButton:{valueFn:function(){return e.Node.create(n(e.UploaderFlash.SELECT_FILES_BUTTON,{selectButtonLabel:this.get("selectButtonLabel")}))}},simLimit:{value:2,validator:function(e,t){return e>=2&&e<=5}},swfURL:{valueFn:function(){var t=e.Env.cdn+"uploader/assets/flashuploader.swf";return e.UA.ie>0?t+"?t="+e.guid("uploader"):t}},tabElements:{value:null},uploadURL:{value:""},retryCount:{value:3}}}),e.UploaderFlash.Queue=r},"3.7.3",{requires:["swf","widget","substitute","base","cssbutton","node","event-custom","file-flash","uploader-queue"]});
diff --git a/js/yui3/uploader-html5/assets/uploader-flash-core.css b/js/yui3/uploader-html5/assets/uploader-flash-core.css
new file mode 100644
index 000000000..6f5f82a0a
--- /dev/null
+++ b/js/yui3/uploader-html5/assets/uploader-flash-core.css
@@ -0,0 +1,10 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-uploader-selectfiles-button {
+ width: 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/js/yui3/uploader-html5/uploader-html5-min.js b/js/yui3/uploader-html5/uploader-html5-min.js
new file mode 100644
index 000000000..0606b4833
--- /dev/null
+++ b/js/yui3/uploader-html5/uploader-html5-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("uploader-html5",function(e,t){function i(e){i.superclass.constructor.apply(this,arguments)}var n=e.substitute,r=e.Uploader.Queue;e.UploaderHTML5=e.extend(i,e.Widget,{_fileInputField:null,_buttonBinding:null,queue:null,initializer:function(){this._fileInputField=null,this.queue=null,this._buttonBinding=null,this._fileList=[],this.publish("fileselect"),this.publish("uploadstart"),this.publish("fileuploadstart"),this.publish("uploadprogress"),this.publish("totaluploadprogress"),this.publish("uploadcomplete"),this.publish("alluploadscomplete"),this.publish("uploaderror"),this.publish("dragenter"),this.publish("dragover"),this.publish("dragleave"),this.publish("drop")},renderUI:function(){var t=this.get("boundingBox"),n=this.get("contentBox"),r=this.get("selectFilesButton");r.setStyles({width:"100%",height:"100%"}),n.append(r),this._fileInputField=e.Node.create(i.HTML5FILEFIELD_TEMPLATE),n.append(this._fileInputField)},bindUI:function(){this._bindSelectButton(),this._setMultipleFiles(),this._setFileFilters(),this._bindDropArea(),this._triggerEnabled(),this.after("multipleFilesChange",this._setMultipleFiles,this),this.after("fileFiltersChange",this._setFileFilters,this),this.after("enabledChange",this._triggerEnabled,this),this.after("selectFilesButtonChange",this._bindSelectButton,this),this.after("dragAndDropAreaChange",this._bindDropArea,this),this.after("tabIndexChange",function(e){this.get("selectFilesButton").set("tabIndex",this.get("tabIndex"))},this),this._fileInputField.on("change",this._updateFileList,this),this.get("selectFilesButton").set("tabIndex",this.get("tabIndex"))},_rebindFileField:function(){this._fileInputField.remove(!0),this._fileInputField=e.Node.create(i.HTML5FILEFIELD_TEMPLATE),this.get("contentBox").append(this._fileInputField),this._fileInputField.on("change",this._updateFileList,this),this._setMultipleFiles(),this._setFileFilters()},_bindDropArea:function(e){var t=e||{prevVal:null};t.prevVal!==null&&(t.prevVal.detach("drop",this._ddEventHandler),t.prevVal.detach("dragenter",this._ddEventHandler),t.prevVal.detach("dragover",this._ddEventHandler),t.prevVal.detach("dragleave",this._ddEventHandler));var n=this.get("dragAndDropArea");n!==null&&(n.on("drop",this._ddEventHandler,this),n.on("dragenter",this._ddEventHandler,this),n.on("dragover",this._ddEventHandler,this),n.on("dragleave",this._ddEventHandler,this))},_bindSelectButton:function(){this._buttonBinding=this.get("selectFilesButton").on("click",this.openFileSelectDialog,this)},_ddEventHandler:function(t){t.stopPropagation(),t.preventDefault();switch(t.type){case"dragenter":this.fire("dragenter");break;case"dragover":this.fire("dragover");break;case"dragleave":this.fire("dragleave");break;case"drop":var n=t._event.dataTransfer.files,r=[],i=this.get("fileFilterFunction");i?e.each(n,function(t){var n=new e.FileHTML5(t);i(n)&&r.push(n)}):e.each(n,function(t){r.push(new e.FileHTML5(t))});if(r.length>0){var s=this.get("fileList");this.set("fileList",this.get("appendNewFiles")?s.concat(r):r),this.fire("fileselect",{fileList:r})}this.fire("drop")}},_setButtonClass:function(e,t){t?this.get("selectFilesButton").addClass(this.get("buttonClassNames")[e]):this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[e])},_setMultipleFiles:function(){this.get("multipleFiles")===!0?this._fileInputField.set("multiple","multiple"):this._fileInputField.set("multiple","")},_setFileFilters:function(){this.get("fileFilters").length>0?this._fileInputField.set("accept",this.get("fileFilters").join(",")):this._fileInputField.set("accept","")},_triggerEnabled:function(){this.get("enabled")&&this._buttonBinding===null?(this._bindSelectButton(),this._setButtonClass("disabled",!1),this.get("selectFilesButton").setAttribute("aria-disabled","false")):!this.get("enabled")&&this._buttonBinding&&(this._buttonBinding.detach(),this._buttonBinding=null,this._setButtonClass("disabled",!0),this.get("selectFilesButton").setAttribute("aria-disabled","true"))},_getFileList:function(e){return this._fileList.concat()},_setFileList:function(e){return this._fileList=e.concat(),this._fileList.concat()},_updateFileList:function(t){var n=t.target.getDOMNode().files,r=[],i=this.get("fileFilterFunction");i?e.each(n,function(t){var n=new e.FileHTML5(t);i(n)&&r.push(n)}):e.each(n,function(t){r.push(new e.FileHTML5(t))});if(r.length>0){var s=this.get("fileList");this.set("fileList",this.get("appendNewFiles")?s.concat(r):r),this.fire("fileselect",{fileList:r})}this._rebindFileField()},_uploadEventHandler:function(e){switch(e.type){case"file:uploadstart":this.fire("fileuploadstart",e);break;case"file:uploadprogress":this.fire("uploadprogress",e);break;case"uploaderqueue:totaluploadprogress":this.fire("totaluploadprogress",e);break;case"file:uploadcomplete":this.fire("uploadcomplete",e);break;case"uploaderqueue:alluploadscomplete":this.queue=null,this.fire("alluploadscomplete",e);break;case"file:uploaderror":case"uploaderqueue:uploaderror":this.fire("uploaderror",e);break;case"file:uploadcancel":case"uploaderqueue:uploadcancel":this.fire("uploadcancel",e)}},openFileSelectDialog:function(){var e=this._fileInputField.getDOMNode();e.click&&e.click()},upload:function(t,n,r){var i=n||this.get("uploadURL"),s=r||this.get("postVarsPerFile"),o=t.get("id");s=s.hasOwnProperty(o)?s[o]:s,t instanceof e.FileHTML5&&(t.on("uploadstart",this._uploadEventHandler,this),t.on("uploadprogress",this._uploadEventHandler,this),t.on("uploadcomplete",this._uploadEventHandler,this),t.on("uploaderror",this._uploadEventHandler,this),t.on("uploadcancel",this._uploadEventHandler,this),t.startUpload(i,s,this.get("fileFieldName")))},uploadAll:function(e,t){this.uploadThese(this.get("fileList"),e,t)},uploadThese:function(t,n,i){if(!this.queue){var s=n||this.get("uploadURL"),o=i||this.get("postVarsPerFile");this.queue=new r({simUploads:this.get("simLimit"),errorAction:this.get("errorAction"),fileFieldName:this.get("fileFieldName"),fileList:t,uploadURL:s,perFileParameters:o,retryCount:this.get("retryCount"),uploadHeaders:this.get("uploadHeaders"),withCredentials:this.get("withCredentials")}),this.queue.on("uploadstart",this._uploadEventHandler,this),this.queue.on("uploadprogress",this._uploadEventHandler,this),this.queue.on("totaluploadprogress",this._uploadEventHandler,this),this.queue.on("uploadcomplete",this._uploadEventHandler,this),this.queue.on("alluploadscomplete",this._uploadEventHandler,this),this.queue.on("uploadcancel",this._uploadEventHandler,this),this.queue.on("uploaderror",this._uploadEventHandler,this),this.queue.startUpload(),this.fire("uploadstart")}else this.queue._currentState===r.UPLOADING&&(this.queue.set("perFileParameters",this.get("postVarsPerFile")),e.each(t,function(e){this.queue.addToQueueBottom(e)},this))}},{HTML5FILEFIELD_TEMPLATE:"<input type='file' style='visibility:hidden; width:0px; height: 0px;'>",SELECT_FILES_BUTTON:"<button type='button' class='yui3-button' role='button' aria-label='{selectButtonLabel}' tabindex='{tabIndex}'>{selectButtonLabel}</button>",TYPE:"html5",NAME:"uploader",ATTRS:{appendNewFiles:{value:!0},buttonClassNames:{value:{hover:"yui3-button-hover",active:"yui3-button-active",disabled:"yui3-button-disabled",focus:"yui3-button-selected"}},dragAndDropArea:{value:null,setter:function(t){return e.one(t)}},enabled:{value:!0},errorAction:{value:"continue",validator:function(e,t){return e===r.CONTINUE||e===r.STOP||e===r.RESTART_ASAP||e===r.RESTART_AFTER}},fileFilters:{value:[]},fileFilterFunction:{value:null},fileFieldName:{value:"Filedata"},fileList:{value:[],getter:"_getFileList",setter:"_setFileList"},multipleFiles:{value:!1},postVarsPerFile:{value:{}},selectButtonLabel:{value:"Select Files"},selectFilesButton:{valueFn:function(){return e.Node.create(n(e.UploaderHTML5.SELECT_FILES_BUTTON,{selectButtonLabel:this.get("selectButtonLabel"),tabIndex:this.get("tabIndex")}))}},simLimit:{value:2,validator:function(e,t){return e>=1&&e<=5}},uploadURL:{value:""},uploadHeaders:{value:{}},withCredentials:{value:!0},retryCount:{value:3}}}),e.UploaderHTML5.Queue=r},"3.7.3",{requires:["widget","node-event-simulate","substitute","file-html5","uploader-queue"]});
diff --git a/js/yui3/uploader-queue/assets/uploader-flash-core.css b/js/yui3/uploader-queue/assets/uploader-flash-core.css
new file mode 100644
index 000000000..6f5f82a0a
--- /dev/null
+++ b/js/yui3/uploader-queue/assets/uploader-flash-core.css
@@ -0,0 +1,10 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-uploader-selectfiles-button {
+ width: 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/js/yui3/uploader-queue/uploader-queue-min.js b/js/yui3/uploader-queue/uploader-queue-min.js
new file mode 100644
index 000000000..ad75741ef
--- /dev/null
+++ b/js/yui3/uploader-queue/uploader-queue-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("uploader-queue",function(e,t){var n=e.Lang,r=e.bind,i=e.config.win,s,o,u,a,f,l,c=function(e){this.queuedFiles=[],this.uploadRetries={},this.numberOfUploads=0,this.currentUploadedByteValues={},this.currentFiles={},this.totalBytesUploaded=0,this.totalBytes=0,c.superclass.constructor.apply(this,arguments)};e.extend(c,e.Base,{_currentState:c.STOPPED,initializer:function(e){},_uploadStartHandler:function(e){var t=e;t.file=e.target,t.originEvent=e,this.fire("uploadstart",t)},_uploadErrorHandler:function(e){var t=this.get("errorAction"),n=e;n.file=e.target,n.originEvent=e,this.numberOfUploads-=1,delete this.currentFiles[e.target.get("id")],this._detachFileEvents(e.target),e.target.cancelUpload();if(t===c.STOP)this.pauseUpload();else if(t===c.RESTART_ASAP){var r=e.target.get("id"),i=this.uploadRetries[r]||0;i<this.get("retryCount")&&(this.uploadRetries[r]=i+1,this.addToQueueTop(e.target)),this._startNextFile()}else if(t===c.RESTART_AFTER){var r=e.target.get("id"),i=this.uploadRetries[r]||0;i<this.get("retryCount")&&(this.uploadRetries[r]=i+1,this.addToQueueBottom(e.target)),this._startNextFile()}this.fire("uploaderror",n)},_startNextFile:function(){if(this.queuedFiles.length>0){var e=this.queuedFiles.shift(),t=e.get("id"),n=this.get("perFileParameters"),r=n.hasOwnProperty(t)?n[t]:n;this.currentUploadedByteValues[t]=0,e.on("uploadstart",this._uploadStartHandler,this),e.on("uploadprogress",this._uploadProgressHandler,this),e.on("uploadcomplete",this._uploadCompleteHandler,this),e.on("uploaderror",this._uploadErrorHandler,this),e.on("uploadcancel",this._uploadCancelHandler,this),e.set("xhrHeaders",this.get("uploadHeaders")),e.set("xhrWithCredentials",this.get("withCredentials")),e.startUpload(this.get("uploadURL"),r,this.get("fileFieldName")),this._registerUpload(e)}},_registerUpload:function(e){this.numberOfUploads+=1,this.currentFiles[e.get("id")]=e},_unregisterUpload:function(e){this.numberOfUploads>0&&(this.numberOfUploads-=1),delete this.currentFiles[e.get("id")],delete this.uploadRetries[e.get("id")],this._detachFileEvents(e)},_detachFileEvents:function(e){e.detach("uploadstart",this._uploadStartHandler),e.detach("uploadprogress",this._uploadProgressHandler),e.detach("uploadcomplete",this._uploadCompleteHandler),e.detach("uploaderror",this._uploadErrorHandler),e.detach("uploadcancel",this._uploadCancelHandler)},_uploadCompleteHandler:function(t){this._unregisterUpload(t.target),this.totalBytesUploaded+=t.target.get("size"),delete this.currentUploadedByteValues[t.target.get("id")],this.queuedFiles.length>0&&this._currentState===c.UPLOADING&&this._startNextFile();var n=t;n.file=t.target,n.originEvent=t;var r=this.totalBytesUploaded;e.each(this.currentUploadedByteValues,function(e){r+=e});var i=Math.min(100,Math.round(1e4*r/this.totalBytes)/100);this.fire("totaluploadprogress",{bytesLoaded:r,bytesTotal:this.totalBytes,percentLoaded:i}),this.fire("uploadcomplete",n),this.queuedFiles.length===0&&this.numberOfUploads<=0&&(this.fire("alluploadscomplete"),this._currentState=c.STOPPED)},_uploadCancelHandler:function(e){var t=e;t.originEvent=e,t.file=e.target,this.fire("uploadcacel",t)},_uploadProgressHandler:function(t){this.currentUploadedByteValues[t.target.get("id")]=t.bytesLoaded;var n=t;n.originEvent=t,n.file=t.target,this.fire("uploadprogress",n);var r=this.totalBytesUploaded;e.each(this.currentUploadedByteValues,function(e){r+=e});var i=Math.min(100,Math.round(1e4*r/this.totalBytes)/100);this.fire("totaluploadprogress",{bytesLoaded:r,bytesTotal:this.totalBytes,percentLoaded:i})},startUpload:function(){this.queuedFiles=this.get("fileList").slice(0),this.numberOfUploads=0,this.currentUploadedByteValues={},this.currentFiles={},this.totalBytesUploaded=0,this._currentState=c.UPLOADING;while(this.numberOfUploads<this.get("simUploads")&&this.queuedFiles.length>0)this._startNextFile()},pauseUpload:function(){this._currentState=c.STOPPED},restartUpload:function(){this._currentState=c.UPLOADING;while(this.numberOfUploads<this.get("simUploads"))this._startNextFile()},forceReupload:function(e){var t=e.get("id");this.currentFiles.hasOwnProperty(t)&&(e.cancelUpload(),this._unregisterUpload(e),this.addToQueueTop(e),this._startNextFile())},addToQueueTop:function(e){this.queuedFiles.unshift(e)},addToQueueBottom:function(e){this.queuedFiles.push(e)},cancelUpload:function(e){if(e){var t=e.get("id");if(this.currentFiles[t])this.currentFiles[t].cancelUpload(),this._unregisterUpload(this.currentFiles[t]),this._currentState===c.UPLOADING&&this._startNextFile();else for(var n=0,r=this.queuedFiles.length;n<r;n++)if(this.queuedFiles[n].get("id")===t){this.queuedFiles.splice(n,1);break}}else{for(var i in this.currentFiles)this.currentFiles[i].cancelUpload(),this._unregisterUpload(this.currentFiles[i]);this.currentUploadedByteValues={},this.currentFiles={},this.totalBytesUploaded=0,this.fire("alluploadscancelled"),this._currentState=c.STOPPED}}},{CONTINUE:"continue",STOP:"stop",RESTART_ASAP:"restartasap",RESTART_AFTER:"restartafter",STOPPED:"stopped",UPLOADING:"uploading",NAME:"uploaderqueue",ATTRS:{simUploads:{value:2,validator:function(e,t){return e>=1&&e<=5}},errorAction:{value:"continue",validator:function(e,t){return e===c.CONTINUE||e===c.STOP||e===c.RESTART_ASAP||e===c.RESTART_AFTER}},bytesUploaded:{readOnly:!0,value:0},bytesTotal:{readOnly:!0,value:0},fileList:{value:[],lazyAdd:!1,setter:function(t){var n=t;return e.Array.each(n,function(e){this.totalBytes+=e.get("size")},this),t}},fileFieldName:{value:"Filedata"},uploadURL:{value:""},uploadHeaders:{value:{}},withCredentials:{value:!0},perFileParameters:{value:{}},retryCount:{value:3}}}),e.namespace("Uploader"),e.Uploader.Queue=c},"3.7.3",{requires:["base"]});
diff --git a/js/yui3/uploader/assets/flashuploader.swf b/js/yui3/uploader/assets/flashuploader.swf
new file mode 100644
index 000000000..73026acb5
--- /dev/null
+++ b/js/yui3/uploader/assets/flashuploader.swf
Binary files differ
diff --git a/js/yui3/uploader/assets/uploader-flash-core.css b/js/yui3/uploader/assets/uploader-flash-core.css
new file mode 100644
index 000000000..6f5f82a0a
--- /dev/null
+++ b/js/yui3/uploader/assets/uploader-flash-core.css
@@ -0,0 +1,10 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-uploader-selectfiles-button {
+ width: 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/js/yui3/uploader/uploader-min.js b/js/yui3/uploader/uploader-min.js
new file mode 100644
index 000000000..60f04100a
--- /dev/null
+++ b/js/yui3/uploader/uploader-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("uploader",function(e,t){var n=e.config.win;n&&n.File&&n.FormData&&n.XMLHttpRequest?e.Uploader=e.UploaderHTML5:e.SWFDetect.isFlashVersionAtLeast(10,0,45)?e.Uploader=e.UploaderFlash:(e.namespace("Uploader"),e.Uploader.TYPE="none")},"3.7.3",{requires:["uploader-html5","uploader-flash"]});
diff --git a/js/yui3/view-node-map/view-node-map-min.js b/js/yui3/view-node-map/view-node-map-min.js
new file mode 100644
index 000000000..11b2b006b
--- /dev/null
+++ b/js/yui3/view-node-map/view-node-map-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("view-node-map",function(e,t){function i(){}var n=e.namespace("View._buildCfg"),r={};n.aggregates||(n.aggregates=[]),n.aggregates.push("getByNode"),i.getByNode=function(t){var n;return e.one(t).ancestor(function(t){return(n=r[e.stamp(t,!0)])||!1},!0),n||null},i._instances=r,i.prototype={initializer:function(){r[e.stamp(this.get("container"))]=this},destructor:function(){var t=e.stamp(this.get("container"),!0);t in r&&delete r[t]}},e.View.NodeMap=i},"3.7.3",{requires:["view"]});
diff --git a/js/yui3/view/view-min.js b/js/yui3/view/view-min.js
new file mode 100644
index 000000000..4ce0baaaa
--- /dev/null
+++ b/js/yui3/view/view-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("view",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}e.View=e.extend(n,e.Base,{containerTemplate:"<div/>",events:{},template:"",_allowAdHocAttrs:!0,initializer:function(t){t||(t={}),t.containerTemplate&&(this.containerTemplate=t.containerTemplate),t.template&&(this.template=t.template),this.events=t.events?e.merge(this.events,t.events):this.events,this.after("containerChange",this._afterContainerChange)},destroy:function(e){return e&&(e.remove||e["delete"])&&this.onceAfter("destroy",function(){this._destroyContainer()}),n.superclass.destroy.call(this)},destructor:function(){this.detachEvents(),delete this._container},attachEvents:function(t){var n=this.get("container"),r=e.Object.owns,i,s,o,u;this.detachEvents(),t||(t=this.events);for(u in t){if(!r(t,u))continue;s=t[u];for(o in s){if(!r(s,o))continue;i=s[o],typeof i=="string"&&(i=this[i]);if(!i)continue;this._attachedViewEvents.push(n.delegate(o,i,u,this))}}return this},create:function(t){return t?e.one(t):e.Node.create(this.containerTemplate)},detachEvents:function(){return e.Array.each(this._attachedViewEvents,function(e){e&&e.detach()}),this._attachedViewEvents=[],this},remove:function(){var e=this.get("container");return e&&e.remove(),this},render:function(){return this},_destroyContainer:function(){var e=this.get("container");e&&e.remove(!0)},_getContainer:function(e){return this._container||(e?(this._container=e,this.attachEvents()):(e=this._container=this.create(),this._set("container",e))),e},_afterContainerChange:function(){this.attachEvents(this.events)}},{NAME:"view",ATTRS:{container:{getter:"_getContainer",setter:e.one,writeOnce:!0}},_NON_ATTRS_CFG:["containerTemplate","events","template"]})},"3.7.3",{requires:["base-build","node-event-delegate"]});
diff --git a/js/yui3/widget-anim/widget-anim-min.js b/js/yui3/widget-anim/widget-anim-min.js
new file mode 100644
index 000000000..f1f4a732b
--- /dev/null
+++ b/js/yui3/widget-anim/widget-anim-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-anim",function(e,t){function b(e){b.superclass.constructor.apply(this,arguments)}var n="boundingBox",r="host",i="node",s="opacity",o="",u="visible",a="destroy",f="hidden",l="rendered",c="start",h="end",p="duration",d="animShow",v="animHide",m="_uiSetVisible",g="animShowChange",y="animHideChange";b.NS="anim",b.NAME="pluginWidgetAnim",b.ANIMATIONS={fadeIn:function(){var t=this.get(r),f=t.get(n),l=new e.Anim({node:f,to:{opacity:1},duration:this.get(p)});return t.get(u)||f.setStyle(s,0),l.on(a,function(){this.get(i).setStyle(s,e.UA.ie?1:o)}),l},fadeOut:function(){return new e.Anim({node:this.get(r).get(n),to:{opacity:0},duration:this.get(p)})}},b.ATTRS={duration:{value:.2},animShow:{valueFn:b.ANIMATIONS.fadeIn},animHide:{valueFn:b.ANIMATIONS.fadeOut}},e.extend(b,e.Plugin.Base,{initializer:function(e){this._bindAnimShow(),this._bindAnimHide(),this.after(g,this._bindAnimShow),this.after(y,this._bindAnimHide),this.beforeHostMethod(m,this._uiAnimSetVisible)},destructor:function(){this.get(d).destroy(),this.get(v).destroy()},_uiAnimSetVisible:function(t){if(this.get(r).get(l))return t?(this.get(v).stop(),this.get(d).run()):(this.get(d).stop(),this.get(v).run()),new e.Do.Prevent},_uiSetVisible:function(e){var t=this.get(r),i=t.getClassName(f);t.get(n).toggleClass(i,!e)},_bindAnimShow:function(){this.get(d).on(c,e.bind(function(){this._uiSetVisible(!0)},this))},_bindAnimHide:function(){this.get(v).after(h,e.bind(function(){this._uiSetVisible(!1)},this))}}),e.namespace("Plugin").WidgetAnim=b},"3.7.3",{requires:["anim-base","plugin","widget"]});
diff --git a/js/yui3/widget-autohide/widget-autohide-min.js b/js/yui3/widget-autohide/widget-autohide-min.js
new file mode 100644
index 000000000..4996d3a81
--- /dev/null
+++ b/js/yui3/widget-autohide/widget-autohide-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-autohide",function(e,t){function m(t){e.after(this._bindUIAutohide,this,f),e.after(this._syncUIAutohide,this,l),this.get(c)&&(this._bindUIAutohide(),this._syncUIAutohide())}var n="widgetAutohide",r="autohide",i="clickoutside",s="focusoutside",o="document",u="key",a="esc",f="bindUI",l="syncUI",c="rendered",h="boundingBox",p="visible",d="Change",v=e.ClassNameManager.getClassName;m.ATTRS={hideOn:{validator:e.Lang.isArray,valueFn:function(){return[{node:e.one(o),eventName:u,keyCode:a}]}}},m.prototype={_uiHandlesAutohide:null,destructor:function(){this._detachUIHandlesAutohide()},_bindUIAutohide:function(){this.after(p+d,this._afterHostVisibleChangeAutohide),this.after("hideOnChange",this._afterHideOnChange)},_syncUIAutohide:function(){this._uiSetHostVisibleAutohide(this.get(p))},_uiSetHostVisibleAutohide:function(t){t?e.later(1,this,"_attachUIHandlesAutohide"):this._detachUIHandlesAutohide()},_attachUIHandlesAutohide:function(){if(this._uiHandlesAutohide)return;var t=this.get(h),n=e.bind(this.hide,this),r=[],i=this,s=this.get("hideOn"),o=0,u={node:undefined,ev:undefined,keyCode:undefined};for(;o<s.length;o++)u.node=s[o].node,u.ev=s[o].eventName,u.keyCode=s[o].keyCode,!u.node&&!u.keyCode&&u.ev?r.push(t.on(u.ev,n)):u.node&&!u.keyCode&&u.ev?r.push(u.node.on(u.ev,n)):u.node&&u.keyCode&&u.ev&&r.push(u.node.on(u.ev,n,u.keyCode));this._uiHandlesAutohide=r},_detachUIHandlesAutohide:function(){e.each(this._uiHandlesAutohide,function(e){e.detach()}),this._uiHandlesAutohide=null},_afterHostVisibleChangeAutohide:function(e){this._uiSetHostVisibleAutohide(e.newVal)},_afterHideOnChange:function(e){this._detachUIHandlesAutohide(),this.get(p)&&this._attachUIHandlesAutohide()}},e.WidgetAutohide=m},"3.7.3",{requires:["base-build","event-key","event-outside","widget"]});
diff --git a/js/yui3/widget-base-ie/assets/widget-base-core.css b/js/yui3/widget-base-ie/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-base-ie/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-base-ie/widget-base-ie-min.js b/js/yui3/widget-base-ie/widget-base-ie-min.js
new file mode 100644
index 000000000..19aabbde8
--- /dev/null
+++ b/js/yui3/widget-base-ie/widget-base-ie-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-base-ie",function(e,t){var n="boundingBox",r="contentBox",i="height",s="offsetHeight",o="",u=e.UA.ie,a=u<7,f=e.Widget.getClassName("tmp","forcesize"),l=e.Widget.getClassName("content","expanded");e.Widget.prototype._uiSizeCB=function(e){var t=this.get(n),c=this.get(r),h=this._bbs;h===undefined&&(this._bbs=h=!(u&&u<8&&t.get("ownerDocument").get("compatMode")!="BackCompat")),h?c.toggleClass(l,e):e?(a&&t.addClass(f),c.set(s,t.get(s)),a&&t.removeClass(f)):c.setStyle(i,o)}},"3.7.3",{requires:["widget-base"]});
diff --git a/js/yui3/widget-base/assets/skins/night/widget-base.css b/js/yui3/widget-base/assets/skins/night/widget-base.css
new file mode 100644
index 000000000..0f909d291
--- /dev/null
+++ b/js/yui3/widget-base/assets/skins/night/widget-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}#yui3-css-stamp.skin-night-widget-base{display:none}
diff --git a/js/yui3/widget-base/assets/skins/sam/widget-base.css b/js/yui3/widget-base/assets/skins/sam/widget-base.css
new file mode 100644
index 000000000..118a6ec1b
--- /dev/null
+++ b/js/yui3/widget-base/assets/skins/sam/widget-base.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}#yui3-css-stamp.skin-sam-widget-base{display:none}
diff --git a/js/yui3/widget-base/assets/widget-base-core.css b/js/yui3/widget-base/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-base/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-base/widget-base-min.js b/js/yui3/widget-base/widget-base-min.js
new file mode 100644
index 000000000..b46fa28c3
--- /dev/null
+++ b/js/yui3/widget-base/widget-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-base",function(e,t){function R(e){var t=this,n,r,i=t.constructor;t._strs={},t._cssPrefix=i.CSS_PREFIX||s(i.NAME.toLowerCase()),e=e||{},R.superclass.constructor.call(t,e),r=t.get(T),r&&(r!==P&&(n=r),t.render(n))}var n=e.Lang,r=e.Node,i=e.ClassNameManager,s=i.getClassName,o,u=e.cached(function(e){return e.substring(0,1).toUpperCase()+e.substring(1)}),a="content",f="visible",l="hidden",c="disabled",h="focused",p="width",d="height",v="boundingBox",m="contentBox",g="parentNode",y="ownerDocument",b="auto",w="srcNode",E="body",S="tabIndex",x="id",T="render",N="rendered",C="destroyed",k="strings",L="<div></div>",A="Change",O="loading",M="_uiSet",_="",D=function(){},P=!0,H=!1,B,j={},F=[f,c,d,p,h,S],I=e.UA.webkit,q={};R.NAME="widget",B=R.UI_SRC="ui",R.ATTRS=j,j[x]={valueFn:"_guid",writeOnce:P},j[N]={value:H,readOnly:P},j[v]={value:null,setter:"_setBB",writeOnce:P},j[m]={valueFn:"_defaultCB",setter:"_setCB",writeOnce:P},j[S]={value:null,validator:"_validTabIndex"},j[h]={value:H,readOnly:P},j[c]={value:H},j[f]={value:P},j[d]={value:_},j[p]={value:_},j[k]={value:{},setter:"_strSetter",getter:"_strGetter"},j[T]={value:H,writeOnce:P},R.CSS_PREFIX=s(R.NAME.toLowerCase()),R.getClassName=function(){return s.apply(i,[R.CSS_PREFIX].concat(e.Array(arguments),!0))},o=R.getClassName,R.getByNode=function(t){var n,i=o();return t=r.one(t),t&&(t=t.ancestor("."+i,!0),t&&(n=q[e.stamp(t,!0)])),n||null},e.extend(R,e.Base,{getClassName:function(){return s.apply(i,[this._cssPrefix].concat(e.Array(arguments),!0))},initializer:function(t){var n=this.get(v);n instanceof r&&this._mapInstance(e.stamp(n)),this._applyParser&&this._applyParser(t)},_mapInstance:function(e){q[e]=this},destructor:function(){var t=this.get(v),n;t instanceof r&&(n=e.stamp(t,!0),n in q&&delete q[n],this._destroyBox())},destroy:function(e){return this._destroyAllNodes=e,R.superclass.destroy.apply(this)},_destroyBox:function(){var e=this.get(v),t=this.get(m),n=this._destroyAllNodes,r;r=e&&e.compareTo(t),this.UI_EVENTS&&this._destroyUIEvents(),this._unbindUI(e),n?(e.empty(),e.remove(P)):(t&&t.remove(P),r||e.remove(P))},render:function(e){return!this.get(C)&&!this.get(N)&&(this.publish(T,{queuable:H,fireOnce:P,defaultTargetOnly:P,defaultFn:this._defRenderFn}),this.fire(T,{parentNode:e?r.one(e):null})),this},_defRenderFn:function(e){this._parentNode=e.parentNode,this.renderer(),this._set(N,P),this._removeLoadingClassNames()},renderer:function(){var e=this;e._renderUI(),e.renderUI(),e._bindUI(),e.bindUI(),e._syncUI(),e.syncUI()},bindUI:D,renderUI:D,syncUI:D,hide:function(){return this.set(f,H)},show:function(){return this.set(f,P)},focus:function(){return this._set(h,P)},blur:function(){return this._set(h,H)},enable:function(){return this.set(c,H)},disable:function(){return this.set(c,P)},_uiSizeCB:function(e){this.get(m).toggleClass(o(a,"expanded"),e)},_renderBox:function(e){var t=this,n=t.get(m),i=t.get(v),s=t.get(w),o=t.DEF_PARENT_NODE,u=s&&s.get(y)||i.get(y)||n.get(y);s&&!s.compareTo(n)&&!n.inDoc(u)&&s.replace(n),!i.compareTo(n.get(g))&&!i.compareTo(n)&&(n.inDoc(u)&&n.replace(i),i.appendChild(n)),e=e||o&&r.one(o),e?e.appendChild(i):i.inDoc(u)||r.one(E).insert(i,0)},_setBB:function(e){return this._setBox(this.get(x),e,this.BOUNDING_TEMPLATE,!0)},_setCB:function(e){return this.CONTENT_TEMPLATE===null?this.get(v):this._setBox(null,e,this.CONTENT_TEMPLATE,!1)},_defaultCB:function(e){return this.get(w)||null},_setBox:function(t,n,i,s){return n=r.one(n),n||(n=r.create(i),s?this._bbFromTemplate=!0:this._cbFromTemplate=!0),n.get(x)||n.set(x,t||e.guid()),n},_renderUI:function(){this._renderBoxClassNames(),this._renderBox(this._parentNode)},_renderBoxClassNames:function(){var e=this._getClasses(),t,n=this.get(v),r;n.addClass(o());for(r=e.length-3;r>=0;r--)t=e[r],n.addClass(t.CSS_PREFIX||s(t.NAME.toLowerCase()));this.get(m).addClass(this.getClassName(a))},_removeLoadingClassNames:function(){var e=this.get(v),t=this.get(m),n=this.getClassName(O),r=o(O);e.removeClass(r).removeClass(n),t.removeClass(r).removeClass(n)},_bindUI:function(){this._bindAttrUI(this._UI_ATTRS.BIND),this._bindDOM()},_unbindUI:function(e){this._unbindDOM(e)},_bindDOM:function(){var t=this.get(v).get(y),n=R._hDocFocus;n||(n=R._hDocFocus=t.on("focus",this._onDocFocus,this),n.listeners={count:0}),n.listeners[e.stamp(this,!0)]=!0,n.listeners.count++,I&&(this._hDocMouseDown=t.on("mousedown",this._onDocMouseDown,this))},_unbindDOM:function(t){var n=R._hDocFocus,r=e.stamp(this,!0),i,s=this._hDocMouseDown;n&&(i=n.listeners,i[r]&&(delete i[r],i.count--),i.count===0&&(n.detach(),R._hDocFocus=null)),I&&s&&s.detach()},_syncUI:function(){this._syncAttrUI(this._UI_ATTRS.SYNC)},_uiSetHeight:function(e){this._uiSetDim(d,e),this._uiSizeCB(e!==_&&e!==b)},_uiSetWidth:function(e){this._uiSetDim(p,e)},_uiSetDim:function(e,t){this.get(v).setStyle(e,n.isNumber(t)?t+this.DEF_UNIT:t)},_uiSetVisible:function(e){this.get(v).toggleClass(this.getClassName(l),!e)},_uiSetDisabled:function(e){this.get(v).toggleClass(this.getClassName(c),e)},_uiSetFocused:function(e,t){var n=this.get(v);n.toggleClass(this.getClassName(h),e),t!==B&&(e?n.focus():n.blur())},_uiSetTabIndex:function(e){var t=this.get(v);n.isNumber(e)?t.set(S,e):t.removeAttribute(S)},_onDocMouseDown:function(e){this._domFocus&&this._onDocFocus(e)},_onDocFocus:function(e){var t=R.getByNode(e.target),n=R._active;n&&n!==t&&(n._domFocus=!1,n._set(h,!1,{src:B}),R._active=null),t&&(t._domFocus=!0,t._set(h,!0,{src:B}),R._active=t)},toString:function(){return this.name+"["+this.get(x)+"]"},DEF_UNIT:"px",DEF_PARENT_NODE:null,CONTENT_TEMPLATE:L,BOUNDING_TEMPLATE:L,_guid:function(){return e.guid()},_validTabIndex:function(e){return n.isNumber(e)||n.isNull(e)},_bindAttrUI:function(e){var t,n=e.length;for(t=0;t<n;t++)this.after(e[t]+A,this._setAttrUI)},_syncAttrUI:function(e){var t,n=e.length,r;for(t=0;t<n;t++)r=e[t],this[M+u(r)](this.get(r))},_setAttrUI:function(e){e.target===this&&this[M+u(e.attrName)](e.newVal,e.src)},_strSetter:function(t){return e.merge(this.get(k),t)},getString:function(e){return this.get(k)[e]},getStrings:function(){return this.get(k)},_UI_ATTRS:{BIND:F,SYNC:F}}),e.Widget=R},"3.7.3",{requires:["attribute","base-base","base-pluginhost","classnamemanager","event-focus","node-base","node-style"],skinnable:!0});
diff --git a/js/yui3/widget-buttons/assets/skins/night/sprite_icons.gif b/js/yui3/widget-buttons/assets/skins/night/sprite_icons.gif
new file mode 100644
index 000000000..fab7acb08
--- /dev/null
+++ b/js/yui3/widget-buttons/assets/skins/night/sprite_icons.gif
Binary files differ
diff --git a/js/yui3/widget-buttons/assets/skins/night/widget-buttons.css b/js/yui3/widget-buttons/assets/skins/night/widget-buttons.css
new file mode 100644
index 000000000..afca9611e
--- /dev/null
+++ b/js/yui3/widget-buttons/assets/skins/night/widget-buttons.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-buttons .yui3-button-close,.yui3-widget-buttons .yui3-button-close .yui3-button-content,.yui3-widget-buttons .yui3-button-close .yui3-button-icon{display:inline-block;*display:inline;zoom:1;width:13px;height:13px;line-height:13px;vertical-align:top}.yui3-widget-buttons .yui3-button-close .yui3-button-icon{background-repeat:no-repeat;background-position:1px 1px}.yui3-skin-night .yui3-widget-buttons .yui3-button-icon{background-image:url(sprite_icons.gif)}#yui3-css-stamp.skin-night-widget-buttons{display:none}
diff --git a/js/yui3/widget-buttons/assets/skins/sam/sprite_icons.gif b/js/yui3/widget-buttons/assets/skins/sam/sprite_icons.gif
new file mode 100644
index 000000000..fa26094f6
--- /dev/null
+++ b/js/yui3/widget-buttons/assets/skins/sam/sprite_icons.gif
Binary files differ
diff --git a/js/yui3/widget-buttons/assets/skins/sam/widget-buttons.css b/js/yui3/widget-buttons/assets/skins/sam/widget-buttons.css
new file mode 100644
index 000000000..bef96b104
--- /dev/null
+++ b/js/yui3/widget-buttons/assets/skins/sam/widget-buttons.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-buttons .yui3-button-close,.yui3-widget-buttons .yui3-button-close .yui3-button-content,.yui3-widget-buttons .yui3-button-close .yui3-button-icon{display:inline-block;*display:inline;zoom:1;width:13px;height:13px;line-height:13px;vertical-align:top}.yui3-widget-buttons .yui3-button-close .yui3-button-icon{background-repeat:no-repeat;background-position:1px 1px}.yui3-skin-sam .yui3-widget-buttons .yui3-button-icon{background-image:url(sprite_icons.gif)}#yui3-css-stamp.skin-sam-widget-buttons{display:none}
diff --git a/js/yui3/widget-buttons/assets/widget-buttons-core.css b/js/yui3/widget-buttons/assets/widget-buttons-core.css
new file mode 100644
index 000000000..3b3773f25
--- /dev/null
+++ b/js/yui3/widget-buttons/assets/widget-buttons-core.css
@@ -0,0 +1,21 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-buttons .yui3-button-close,
+.yui3-widget-buttons .yui3-button-close .yui3-button-content,
+.yui3-widget-buttons .yui3-button-close .yui3-button-icon {
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+ width: 13px;
+ height: 13px;
+ line-height: 13px;
+ vertical-align: top;
+}
+.yui3-widget-buttons .yui3-button-close .yui3-button-icon {
+ background-repeat: no-repeat;
+ background-position: 1px 1px;
+}
diff --git a/js/yui3/widget-buttons/widget-buttons-min.js b/js/yui3/widget-buttons/widget-buttons-min.js
new file mode 100644
index 000000000..a59859aef
--- /dev/null
+++ b/js/yui3/widget-buttons/widget-buttons-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-buttons",function(e,t){function p(e){return!!e.getDOMNode}function d(){this._stdModNode||e.error("WidgetStdMod must be added to a Widget before WidgetButtons."),this._buttonsHandles={}}var n=e.Array,r=e.Lang,i=e.Object,s=e.Plugin.Button,o=e.Widget,u=e.WidgetStdMod,a=e.ClassNameManager.getClassName,f=r.isArray,l=r.isNumber,c=r.isString,h=r.isValue;d.ATTRS={buttons:{getter:"_getButtons",setter:"_setButtons",value:{}},defaultButton:{readOnly:!0,value:null}},d.CLASS_NAMES={button:a("button"),buttons:o.getClassName("buttons"),primary:a("button","primary")},d.HTML_PARSER={buttons:function(e){return this._parseButtons(e)}},d.NON_BUTTON_NODE_CFG=["action","classNames","context","events","isDefault","section"],d.prototype={BUTTONS:{},BUTTONS_TEMPLATE:"<span />",DEFAULT_BUTTONS_SECTION:u.FOOTER,initializer:function(){this._mapButtons(this.get("buttons")),this._updateDefaultButton(),this.after({buttonsChange:e.bind("_afterButtonsChange",this),defaultButtonChange:e.bind("_afterDefaultButtonChange",this)}),e.after(this._bindUIButtons,this,"bindUI"),e.after(this._syncUIButtons,this,"syncUI")},destructor:function(){i.each(this._buttonsHandles,function(e){e.detach()}),delete this._buttonsHandles,delete this._buttonsMap,delete this._defaultButton},addButton:function(e,t,r){var i=this.get("buttons"),s,o;return p(e)||(e=this._mergeButtonConfig(e),t||(t=e.section)),t||(t=this.DEFAULT_BUTTONS_SECTION),s=i[t]||(i[t]=[]),l(r)||(r=s.length),s.splice(r,0,e),o=n.indexOf(s,e),this.set("buttons",i,{button:e,section:t,index:o,src:"add"}),this},getButton:function(e,t){if(!h(e))return;var n=this._buttonsMap,r;return t||(t=this.DEFAULT_BUTTONS_SECTION),l(e)?(r=this.get("buttons"),r[t]&&r[t][e]):arguments.length>1?n[t+":"+e]:n[e]},removeButton:function(e,t){if(!h(e))return this;var r=this.get("buttons"),s;return l(e)?(t||(t=this.DEFAULT_BUTTONS_SECTION),s=e,e=r[t][s]):(c(e)&&(e=this.getButton.apply(this,arguments)),i.some(r,function(r,i){s=n.indexOf(r,e);if(s>-1)return t=i,!0})),e&&s>-1&&(r[t].splice(s,1),this.set("buttons",r,{button:e,section:t,index:s,src:"remove"})),this},_bindUIButtons:function(){var t=e.bind("_afterContentChangeButtons",this);this.after({visibleChange:e.bind("_afterVisibleChangeButtons",this),headerContentChange:t,bodyContentChange:t,footerContentChange:t})},_createButton:function(t){var r,i,o,u,a,f,l,h;if(p(t))return e.one(t.getDOMNode()).plug(s);r=e.merge({context:this,events:"click",label:t.value},t),i=e.merge(r),o=d.NON_BUTTON_NODE_CFG;for(u=0,a=o.length;u<a;u+=1)delete i[o[u]];return t=s.createNode(i),l=r.context,f=r.action,c(f)&&(f=e.bind(f,l)),h=t.on(r.events,f,l),this._buttonsHandles[e.stamp(t,!0)]=h,t.setData("name",this._getButtonName(r)),t.setData("default",this._getButtonDefault(r)),n.each(n(r.classNames),t.addClass,t),t},_getButtonContainer:function(t,n){var r=u.SECTION_CLASS_NAMES[t],i=d.CLASS_NAMES.buttons,s=this.get("contentBox"),o,a;return o="."+r+" ."+i,a=s.one(o),!a&&n&&(a=e.Node.create(this.BUTTONS_TEMPLATE),a.addClass(i)),a},_getButtonDefault:function(e){var t=p(e)?e.getData("default"):e.isDefault;return c(t)?t.toLowerCase()==="true":!!t},_getButtonName:function(e){var t;return p(e)?t=e.getData("name")||e.get("name"):t=e&&(e.name||e.type),t},_getButtons:function(e){var t={};return i.each(e,function(e,n){t[n]=e.concat()}),t},_mapButton:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i=this._getButtonDefault(e);r&&(n[r]=e,n[t+":"+r]=e),i&&(this._defaultButton=e)},_mapButtons:function(e){this._buttonsMap={},this._defaultButton=null,i.each(e,function(e,t){var n,r;for(n=0,r=e.length;n<r;n+=1)this._mapButton(e[n],t)},this)},_mergeButtonConfig:function(t){var n,r,i,s,o,u;return t=c(t)?{name:t}:e.merge(t),t.srcNode&&(s=t.srcNode,o=s.get("tagName").toLowerCase(),u=s.get(o==="input"?"value":"text"),n={disabled:!!s.get("disabled"),isDefault:this._getButtonDefault(s),name:this._getButtonName(s)},u&&(n.label=u),e.mix(t,n,!1,null,0,!0)),i=this._getButtonName(t),r=this.BUTTONS&&this.BUTTONS[i],r&&e.mix(t,r,!1,null,0,!0),t},_parseButtons:function(e){var t="."+d.CLASS_NAMES.button,r=["header","body","footer"],i=null;return n.each(r,function(e){var n=this._getButtonContainer(e),r=n&&n.all(t),s;if(!r||r.isEmpty())return;s=[],r.each(function(e){s.push({srcNode:e})}),i||(i={}),i[e]=s},this),i},_setButtons:function(e){function r(e,r){if(!f(e))return;var i,s,o,u;for(i=0,s=e.length;i<s;i+=1)o=e[i],u=r,p(o)||(o=this._mergeButtonConfig(o),u||(u=o.section)),o=this._createButton(o),u||(u=t),(n[u]||(n[u]=[])).push(o)}var t=this.DEFAULT_BUTTONS_SECTION,n={};return f(e)?r.call(this,e):i.each(e,r,this),n},_syncUIButtons:function(){this._uiSetButtons(this.get("buttons")),this._uiSetDefaultButton(this.get("defaultButton")),this._uiSetVisibleButtons(this.get("visible"))},_uiInsertButton:function(e,t,n){var r=d.CLASS_NAMES.button,i=this._getButtonContainer(t,!0),s=i.all("."+r);i.insertBefore(e,s.item(n)),this.setStdModContent(t,i,"after")},_uiRemoveButton:function(t,n,r){var i=e.stamp(t,this),s=this._buttonsHandles,o=s[i],u,a;o&&o.detach(),delete s[i],t.remove(),r||(r={}),r.preserveContent||(u=this._getButtonContainer(n),a=d.CLASS_NAMES.button,u&&u.all("."+a).isEmpty()&&(u.remove(),this._updateContentButtons(n)))},_uiSetButtons:function(e){var t=d.CLASS_NAMES.button,r=["header","body","footer"];n.each(r,function(n){var r=e[n]||[],i=r.length,s=this._getButtonContainer(n,i),o=!1,u,a,f,l;if(!s)return;u=s.all("."+t);for(a=0;a<i;a+=1)f=r[a],l=u.indexOf(f),l>-1?(u.splice(l,1),l!==a&&(s.insertBefore(f,a+1),o=!0)):(s.appendChild(f),o=!0);u.each(function(e){this._uiRemoveButton(e,n,{preserveContent:!0}),o=!0},this);if(i===0){s.remove(),this._updateContentButtons(n);return}o&&this.setStdModContent(n,s,"after")},this)},_uiSetDefaultButton:function(e,t){var n=d.CLASS_NAMES.primary;e&&e.addClass(n),t&&t.removeClass(n)},_uiSetVisibleButtons:function(e){if(!e)return;var t=this.get("defaultButton");t&&t.focus()},_unMapButton:function(e,t){var n=this._buttonsMap,r=this._getButtonName(e),i;r&&(n[r]===e&&delete n[r],i=t+":"+r,n[i]===e&&delete n[i]),this._defaultButton===e&&(this._defaultButton=null)},_updateDefaultButton:function(){var e=this._defaultButton;this.get("defaultButton")!==e&&this._set("defaultButton",e)},_updateContentButtons:function(e){var t=this.getStdModNode(e).get("childNodes");this.set(e+"Content",t.isEmpty()?null:t,{src:"buttons"})},_afterButtonsChange:function(e){var t=e.newVal,n=e.section,r=e.index,i=e.src,s;if(i==="add"){s=t[n][r],this._mapButton(s,n),this._updateDefaultButton(),this._uiInsertButton(s,n,r);return}if(i==="remove"){s=e.button,this._unMapButton(s,n),this._updateDefaultButton(),this._uiRemoveButton(s,n);return}this._mapButtons(t),this._updateDefaultButton(),this._uiSetButtons(t)},_afterContentChangeButtons:function(e){var t=e.src,n=e.stdModPosition,r=!n||n===u.REPLACE;r&&t!=="buttons"&&t!==o.UI_SRC&&this._uiSetButtons(this.get("buttons"))},_afterDefaultButtonChange:function(e){this._uiSetDefaultButton(e.newVal,e.prevVal)},_afterVisibleChangeButtons:function(e){this._uiSetVisibleButtons(e.newVal)}},e.WidgetButtons=d},"3.7.3",{requires:["button-plugin","cssbutton","widget-stdmod"]});
diff --git a/js/yui3/widget-child/widget-child-min.js b/js/yui3/widget-child/widget-child-min.js
new file mode 100644
index 000000000..6f3d7d844
--- /dev/null
+++ b/js/yui3/widget-child/widget-child-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-child",function(e,t){function r(){e.after(this._syncUIChild,this,"syncUI"),e.after(this._bindUIChild,this,"bindUI")}var n=e.Lang;r.ATTRS={selected:{value:0,validator:n.isNumber},index:{readOnly:!0,getter:function(){var e=this.get("parent"),t=-1;return e&&(t=e.indexOf(this)),t}},parent:{readOnly:!0},depth:{readOnly:!0,getter:function(){var e=this.get("parent"),t=this.get("root"),n=-1;while(e){n+=1;if(e==t)break;e=e.get("parent")}return n}},root:{readOnly:!0,getter:function(){var t=function(n){var r=n.get("parent"),i=n.ROOT_TYPE,s=r;return i&&(s=r&&e.instanceOf(r,i)),s?t(r):n};return t(this)}}},r.prototype={ROOT_TYPE:null,_getUIEventNode:function(){var e=this.get("root"),t;return e&&(t=e.get("boundingBox")),t},next:function(e){var t=this.get("parent"),n;return t&&(n=t.item(this.get("index")+1)),!n&&e&&(n=t.item(0)),n},previous:function(e){var t=this.get("parent"),n=this.get("index"),r;return t&&n>0&&(r=t.item([n-1])),!r&&e&&(r=t.item(t.size()-1)),r},remove:function(t){var r,i;return n.isNumber(t)?i=e.WidgetParent.prototype.remove.apply(this,arguments):(r=this.get("parent"),r&&(i=r.remove(this.get("index")))),i},isRoot:function(){return this==this.get("root")},ancestor:function(e){var t=this.get("root"),n;if(this.get("depth")>e){n=this.get("parent");while(n!=t&&n.get("depth")>e)n=n.get("parent")}return n},_uiSetChildSelected:function(e){var t=this.get("boundingBox"),n=this.getClassName("selected");e===0?t.removeClass(n):t.addClass(n)},_afterChildSelectedChange:function(e){this._uiSetChildSelected(e.newVal)},_syncUIChild:function(){this._uiSetChildSelected(this.get("selected"))},_bindUIChild:function(){this.after("selectedChange",this._afterChildSelectedChange)}},e.WidgetChild=r},"3.7.3",{requires:["base-build","widget"]});
diff --git a/js/yui3/widget-htmlparser/assets/widget-base-core.css b/js/yui3/widget-htmlparser/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-htmlparser/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-htmlparser/widget-htmlparser-min.js b/js/yui3/widget-htmlparser/widget-htmlparser-min.js
new file mode 100644
index 000000000..8382e0868
--- /dev/null
+++ b/js/yui3/widget-htmlparser/widget-htmlparser-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-htmlparser",function(e,t){var n=e.Widget,r=e.Node,i=e.Lang,s="srcNode",o="contentBox";n.HTML_PARSER={},n._buildCfg={aggregates:["HTML_PARSER"]},n.ATTRS[s]={value:null,setter:r.one,getter:"_getSrcNode",writeOnce:!0},e.mix(n.prototype,{_getSrcNode:function(e){return e||this.get(o)},_applyParsedConfig:function(t,n,r){return r?e.mix(n,r,!1):n},_applyParser:function(t){var n=this,r=this._getNodeToParse(),s=n._getHtmlParser(),o,u;s&&r&&e.Object.each(s,function(e,t,s){u=null,i.isFunction(e)?u=e.call(n,r):i.isArray(e)?(u=r.all(e[0]),u.isEmpty()&&(u=null)):u=r.one(e),u!==null&&u!==undefined&&(o=o||{},o[t]=u)}),t=n._applyParsedConfig(r,t,o)},_getNodeToParse:function(){var e=this.get("srcNode");return this._cbFromTemplate?null:e},_getHtmlParser:function(){var t=this._getClasses(),n={},r,i;for(r=t.length-1;r>=0;r--)i=t[r].HTML_PARSER,i&&e.mix(n,i,!0);return n}})},"3.7.3",{requires:["widget-base"]});
diff --git a/js/yui3/widget-locale/assets/widget-base-core.css b/js/yui3/widget-locale/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-locale/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-locale/widget-locale-min.js b/js/yui3/widget-locale/widget-locale-min.js
new file mode 100644
index 000000000..2f68fc772
--- /dev/null
+++ b/js/yui3/widget-locale/widget-locale-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-locale",function(e,t){var n=!0,r="locale",i="initValue",s="-",o="",u=e.Widget;u.ATTRS[r]={value:"en"},u.ATTRS.strings.lazyAdd=!1,e.mix(u.prototype,{_setStrings:function(t,r){var i=this._strs;return r=r.toLowerCase(),i[r]||(i[r]={}),e.aggregate(i[r],t,n),i[r]},_getStrings:function(e){return this._strs[e.toLowerCase()]},getStrings:function(t){t=(t||this.get(r)).toLowerCase();var i=this.getDefaultLocale().toLowerCase(),u=this._getStrings(i),a=u?e.merge(u):{},f=t.split(s),l,c,h,p;if(t!==i||f.length>1){p=o;for(c=0,h=f.length;c<h;++c)p+=f[c],l=this._getStrings(p),l&&e.aggregate(a,l,n),p+=s}return a},getString:function(e,t){t=(t||this.get(r)).toLowerCase();var n=this.getDefaultLocale().toLowerCase(),i=this._getStrings(n)||{},o=i[e],u=t.lastIndexOf(s);if(t!==n||u!=-1)do{i=this._getStrings(t);if(i&&e in i){o=i[e];break}u=t.lastIndexOf(s),u!=-1&&(t=t.substring(0,u))}while(u!=-1);return o},getDefaultLocale:function(){return this._state.get(r,i)},_strSetter:function(e){return this._setStrings(e,this.get(r))},_strGetter:function(e){return this._getStrings(this.get(r))}},!0)},"3.7.3",{requires:["widget-base"]});
diff --git a/js/yui3/widget-modality/assets/skins/night/widget-modality.css b/js/yui3/widget-modality/assets/skins/night/widget-modality.css
new file mode 100644
index 000000000..713d1ea54
--- /dev/null
+++ b/js/yui3/widget-modality/assets/skins/night/widget-modality.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-night .yui3-widget-mask{background-color:black;zoom:1;-ms-filter:"alpha(opacity=40)";filter:alpha(opacity=40);opacity:.4}#yui3-css-stamp.skin-night-widget-modality{display:none}
diff --git a/js/yui3/widget-modality/assets/skins/sam/widget-modality.css b/js/yui3/widget-modality/assets/skins/sam/widget-modality.css
new file mode 100644
index 000000000..b3c0198df
--- /dev/null
+++ b/js/yui3/widget-modality/assets/skins/sam/widget-modality.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-skin-sam .yui3-widget-mask{background-color:black;zoom:1;-ms-filter:"alpha(opacity=40)";filter:alpha(opacity=40);opacity:.4}#yui3-css-stamp.skin-sam-widget-modality{display:none}
diff --git a/js/yui3/widget-modality/assets/widget-modality-core.css b/js/yui3/widget-modality/assets/widget-modality-core.css
new file mode 100644
index 000000000..4ec19f46a
--- /dev/null
+++ b/js/yui3/widget-modality/assets/widget-modality-core.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+/* WidgetModality core styles */
diff --git a/js/yui3/widget-modality/widget-modality-min.js b/js/yui3/widget-modality/widget-modality-min.js
new file mode 100644
index 000000000..9e634c684
--- /dev/null
+++ b/js/yui3/widget-modality/widget-modality-min.js
@@ -0,0 +1,9 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-modality",function(e,t){function y(e){}var n="widget",r="renderUI",i="bindUI",s="syncUI",o="boundingBox",u="contentBox",a="visible",f="zIndex",l="Change",c=e.Lang.isBoolean,h=e.ClassNameManager.getClassName,p="maskShow",d="maskHide",v="clickoutside",m="focusoutside",g=function(){
+/*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */
+;var t=e.config.doc,n=null,r,i;return t.createElement&&(r=t.createElement("div"),r&&r.style&&(r.style.position="fixed",r.style.top="10px",i=t.body,i&&i.appendChild&&i.removeChild&&(i.appendChild(r),n=r.offsetTop===10,i.removeChild(r)))),n}(),b="modal",w="mask",E={modal:h(n,b),mask:h(n,w)};y.ATTRS={maskNode:{getter:"_getMaskNode",readOnly:!0},modal:{value:!1,validator:c},focusOn:{valueFn:function(){return[{eventName:v},{eventName:m}]},validator:e.Lang.isArray}},y.CLASSES=E,y._GET_MASK=function(){var t=e.one("."+E.mask),n=e.one("win");return t?t:(t=e.Node.create("<div></div>").addClass(E.mask),g?t.setStyles({position:"fixed",width:"100%",height:"100%",top:"0",left:"0",display:"block"}):t.setStyles({position:"absolute",width:n.get("winWidth")+"px",height:n.get("winHeight")+"px",top:"0",left:"0",display:"block"}),t)},y.STACK=[],y.prototype={initializer:function(){e.after(this._renderUIModal,this,r),e.after(this._syncUIModal,this,s),e.after(this._bindUIModal,this,i)},destructor:function(){this._uiSetHostVisibleModal(!1)},_uiHandlesModal:null,_renderUIModal:function(){var e=this.get(o);this._repositionMask(this),e.addClass(E.modal)},_bindUIModal:function(){this.after(a+l,this._afterHostVisibleChangeModal),this.after(f+l,this._afterHostZIndexChangeModal),this.after("focusOnChange",this._afterFocusOnChange),(!g||e.UA.ios&&e.UA.ios<5||e.UA.android&&e.UA.android<3)&&e.one("win").on("scroll",this._resyncMask,this)},_syncUIModal:function(){this._uiSetHostVisibleModal(this.get(a)),this._uiSetHostZIndexModal(this.get(f))},_focus:function(e){var t=this.get(o),n=t.get("tabIndex");t.set("tabIndex",n>=0?n:0),this.focus()},_blur:function(){this.blur()},_getMaskNode:function(){return y._GET_MASK()},_uiSetHostVisibleModal:function(t){var n=y.STACK,r=this.get("maskNode"),i=this.get("modal"),s,o;t?(e.Array.each(n,function(e){e._detachUIHandlesModal(),e._blur()}),n.unshift(this),this._repositionMask(this),this._uiSetHostZIndexModal(this.get(f)),i&&(r.show(),e.later(1,this,"_attachUIHandlesModal"),this._focus())):(o=e.Array.indexOf(n,this),o>=0&&n.splice(o,1),this._detachUIHandlesModal(),this._blur(),n.length?(s=n[0],this._repositionMask(s),s._uiSetHostZIndexModal(s.get(f)),s.get("modal")&&(e.later(1,s,"_attachUIHandlesModal"),s._focus())):r.getStyle("display")==="block"&&r.hide())},_uiSetHostZIndexModal:function(e){this.get("modal")&&this.get("maskNode").setStyle(f,e||0)},_attachUIHandlesModal:function(){if(this._uiHandlesModal||y.STACK[0]!==this)return;var t=this.get(o),n=this.get("maskNode"),r=this.get("focusOn"),i=e.bind(this._focus,this),s=[],u,a,f;for(u=0,a=r.length;u<a;u++)f={},f.node=r[u].node,f.ev=r[u].eventName,f.keyCode=r[u].keyCode,!f.node&&!f.keyCode&&f.ev?s.push(t.on(f.ev,i)):f.node&&!f.keyCode&&f.ev?s.push(f.node.on(f.ev,i)):f.node&&f.keyCode&&f.ev?s.push(f.node.on(f.ev,i,f.keyCode)):e.Log('focusOn ATTR Error: The event with name "'+f.ev+'" could not be attached.');g||s.push(e.one("win").on("scroll",e.bind(function(e){n.setStyle("top",n.get("docScrollY"))},this))),this._uiHandlesModal=s},_detachUIHandlesModal:function(){e.each(this._uiHandlesModal,function(e){e.detach()}),this._uiHandlesModal=null},_afterHostVisibleChangeModal:function(e){this._uiSetHostVisibleModal(e.newVal)},_afterHostZIndexChangeModal:function(e){this._uiSetHostZIndexModal(e.newVal)},isNested:function(){var e=y.STACK.length,t=e>1?!0:!1;return t},_repositionMask:function(t){var n=this.get("modal"),r=t.get("modal"),i=this.get("maskNode"),s,u;if(n&&!r)i.remove(),this.fire(d);else if(!n&&r||n&&r)i.remove(),this.fire(d),s=t.get(o),u=s.get("parentNode")||e.one("body"),u.insert(i,u.get("firstChild")),this.fire(p)},_resyncMask:function(e){var t=e.currentTarget,n=t.get("docScrollX"),r=t.get("docScrollY"),i=t.get("innerWidth")||t.get("winWidth"),s=t.get("innerHeight")||t.get("winHeight"),o=this.get("maskNode");o.setStyles({top:r+"px",left:n+"px",width:i+"px",height:s+"px"})},_afterFocusOnChange:function(e){this._detachUIHandlesModal(),this.get(a)&&this._attachUIHandlesModal()}},e.WidgetModality=y},"3.7.3",{requires:["base-build","event-outside","widget"],skinnable:!0});
diff --git a/js/yui3/widget-parent/widget-parent-min.js b/js/yui3/widget-parent/widget-parent-min.js
new file mode 100644
index 000000000..2429e4e8a
--- /dev/null
+++ b/js/yui3/widget-parent/widget-parent-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-parent",function(e,t){function s(t){this.publish("addChild",{defaultTargetOnly:!0,defaultFn:this._defAddChildFn}),this.publish("removeChild",{defaultTargetOnly:!0,defaultFn:this._defRemoveChildFn}),this._items=[];var n,r;t&&t.children&&(n=t.children,r=this.after("initializedChange",function(e){this._add(n),r.detach()})),e.after(this._renderChildren,this,"renderUI"),e.after(this._bindUIParent,this,"bindUI"),this.after("selectionChange",this._afterSelectionChange),this.after("selectedChange",this._afterParentSelectedChange),this.after("activeDescendantChange",this._afterActiveDescendantChange),this._hDestroyChild=this.after("*:destroy",this._afterDestroyChild),this.after("*:focusedChange",this._updateActiveDescendant)}var n=e.Lang,r="rendered",i="boundingBox";s.ATTRS={defaultChildType:{setter:function(t){var r=e.Attribute.INVALID_VALUE,i=n.isString(t)?e[t]:t;return n.isFunction(i)&&(r=i),r}},activeDescendant:{readOnly:!0},multiple:{value:!1,validator:n.isBoolean,writeOnce:!0,getter:function(e){var t=this.get("root");return t&&t!=this?t.get("multiple"):e}},selection:{readOnly:!0,setter:"_setSelection",getter:function(t){var r=n.isArray(t)?new e.ArrayList(t):t;return r}},selected:{setter:function(t){var n=t;return t===1&&!this.get("multiple")&&(n=e.Attribute.INVALID_VALUE),n}}},s.prototype={destructor:function(){this._destroyChildren()},_afterDestroyChild:function(e){var t=e.target;t.get("parent")==this&&t.remove()},_afterSelectionChange:function(t){if(t.target==this&&t.src!=this){var n=t.newVal,r=0;n&&(r=2,e.instanceOf(n,e.ArrayList)&&n.size()===this.size()&&(r=1)),this.set("selected",r,{src:this})}},_afterActiveDescendantChange:function(e){var t=this.get("parent");t&&t._set("activeDescendant",e.newVal)},_afterParentSelectedChange:function(e){var t=e.newVal;this==e.target&&e.src!=this&&(t===0||t===1)&&this.each(function(e){e.set("selected",t,{src:this})},this)},_setSelection:function(e){var t=null,n;return this.get("multiple")&&!this.isEmpty()?(n=[],this.each(function(e){e.get("selected")>0&&n.push(e)}),n.length>0&&(t=n)):e.get("selected")>0&&(t=e),t},_updateSelection:function(e){var t=e.target,n;t.get("parent")==this&&(e.src!="_updateSelection"&&(n=this.get("selection"),!this.get("multiple")&&n&&e.newVal>0&&n.set("selected",0,{src:"_updateSelection"}),this._set("selection",t)),e.src==this&&this._set("selection",t,{src:this}))},_updateActiveDescendant:function(e){var t=e.newVal===!0?e.target:null;this._set("activeDescendant",t)},_createChild:function(t){var r=this.get("defaultChildType"),i=t.childType||t.type,s,o,u;return i&&(o=n.isString(i)?e[i]:i),n.isFunction(o)?u=o:r&&(u=r),u?s=new u(t):e.error("Could not create a child instance because its constructor is either undefined or invalid."),s},_defAddChildFn:function(t){var r=t.child,i=t.index,s=this._items;r.get("parent")&&r.remove(),n.isNumber(i)?s.splice(i,0,r):s.push(r),r._set("parent",this),r.addTarget(this),t.index=r.get("index"),r.after("selectedChange",e.bind(this._updateSelection,this))},_defRemoveChildFn:function(e){var t=e.child,n=e.index,r=this._items;t.get("focused")&&t.blur(),t.get("selected")&&t.set("selected",0),r.splice(n,1),t.removeTarget(this),t._oldParent=t.get("parent"),t._set("parent",null)},_add:function(t,r){var i,s,o;return n.isArray(t)?(i=[],e.each(t,function(e,t){s=this._add(e,r+t),s&&i.push(s)},this),i.length>0&&(o=i)):(e.instanceOf(t,e.Widget)?s=t:s=this._createChild(t),s&&this.fire("addChild",{child:s,index:r})&&(o=s)),o},add:function(){var t=this._add.apply(this,arguments),r=t?n.isArray(t)?t:[t]:[];return new e.ArrayList(r)},remove:function(e){var t=this._items[e],n;return t&&this.fire("removeChild",{child:t,index:e})&&(n=t),n},removeAll:function(){var t=[],n;return e.each(this._items.concat(),function(){n=this.remove(0),n&&t.push(n)},this),new e.ArrayList(t)},selectChild:function(e){this.item(e).set("selected",1)},selectAll:function(){this.set("selected",1)},deselectAll:function(){this.set("selected",0)},_uiAddChild:function(e,t){e.render(t);var n=e.get("boundingBox"),s,o=e.next(!1),u;o&&o.get(r)?(s=o.get(i),s.insert(n,"before")):(u=e.previous(!1),u&&u.get(r)?(s=u.get(i),s.insert(n,"after")):t.contains(n)||t.appendChild(n))},_uiRemoveChild:function(e){e.get("boundingBox").remove()},_afterAddChild:function(e){var t=e.child;t.get("parent")==this&&this._uiAddChild(t,this._childrenContainer)},_afterRemoveChild:function(e){var t=e.child;t._oldParent==this&&this._uiRemoveChild(t)},_bindUIParent:function(){this.after("addChild",this._afterAddChild),this.after("removeChild",this._afterRemoveChild)},_renderChildren:function(){var e=this._childrenContainer||this.get("contentBox");this._childrenContainer=e,this.each(function(t){t.render(e)})},_destroyChildren:function(){this._hDestroyChild.detach(),this.each(function(e){e.destroy()})}},e.augment(s,e.ArrayList),e.WidgetParent=s},"3.7.3",{requires:["arraylist","base-build","widget"]});
diff --git a/js/yui3/widget-position-align/widget-position-align-min.js b/js/yui3/widget-position-align/widget-position-align-min.js
new file mode 100644
index 000000000..f1a5c67e4
--- /dev/null
+++ b/js/yui3/widget-position-align/widget-position-align-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-position-align",function(e,t){function c(t){this._posNode||e.error("WidgetPosition needs to be added to the Widget, before WidgetPositionAlign is added"),e.after(this._bindUIPosAlign,this,"bindUI"),e.after(this._syncUIPosAlign,this,"syncUI")}var n=e.Lang,r="align",i="alignOn",s="visible",o="boundingBox",u="offsetWidth",a="offsetHeight",f="region",l="viewportRegion";c.ATTRS={align:{value:null},centered:{setter:"_setAlignCenter",lazyAdd:!1,value:!1},alignOn:{value:[],validator:e.Lang.isArray}},c.TL="tl",c.TR="tr",c.BL="bl",c.BR="br",c.TC="tc",c.RC="rc",c.BC="bc",c.LC="lc",c.CC="cc",c.prototype={_posAlignUIHandles:null,destructor:function(){this._detachPosAlignUIHandles()},_bindUIPosAlign:function(){this.after("alignChange",this._afterAlignChange),this.after("alignOnChange",this._afterAlignOnChange),this.after("visibleChange",this._syncUIPosAlign)},_syncUIPosAlign:function(){var e=this.get(r);this._uiSetVisiblePosAlign(this.get(s)),e&&this._uiSetAlign(e.node,e.points)},align:function(e,t){return arguments.length?this.set(r,{node:e,points:t}):this._syncUIPosAlign(),this},centered:function(e){return this.align(e,[c.CC,c.CC])},_setAlignCenter:function(e){return e&&this.set(r,{node:e===!0?null:e,points:[c.CC,c.CC]}),e},_uiSetAlign:function(t,r){if(!n.isArray(r)||r.length!==2){e.error("align: Invalid Points Arguments");return}var i=this._getRegion(t),s,o,u;if(!i)return;s=r[0],o=r[1];switch(o){case c.TL:u=[i.left,i.top];break;case c.TR:u=[i.right,i.top];break;case c.BL:u=[i.left,i.bottom];break;case c.BR:u=[i.right,i.bottom];break;case c.TC:u=[i.left+Math.floor(i.width/2),i.top];break;case c.BC:u=[i.left+Math.floor(i.width/2),i.bottom];break;case c.LC:u=[i.left,i.top+Math.floor(i.height/2)];break;case c.RC:u=[i.right,i.top+Math.floor(i.height/2)];break;case c.CC:u=[i.left+Math.floor(i.width/2),i.top+Math.floor(i.height/2)];break;default:}u&&this._doAlign(s,u[0],u[1])},_uiSetVisiblePosAlign:function(e){e?this._attachPosAlignUIHandles():this._detachPosAlignUIHandles()},_attachPosAlignUIHandles:function(){if(this._posAlignUIHandles)return;var t=this.get(o),n=e.bind(this._syncUIPosAlign,this),r=[];e.Array.each(this.get(i),function(i){var s=i.eventName,o=e.one(i.node)||t;s&&r.push(o.on(s,n))}),this._posAlignUIHandles=r},_detachPosAlignUIHandles:function(){var t=this._posAlignUIHandles;t&&((new e.EventHandle(t)).detach(),this._posAlignUIHandles=null)},_doAlign:function(e,t,n){var r=this._posNode,i;switch(e){case c.TL:i=[t,n];break;case c.TR:i=[t-r.get(u),n];break;case c.BL:i=[t,n-r.get(a)];break;case c.BR:i=[t-r.get(u),n-r.get(a)];break;case c.TC:i=[t-r.get(u)/2,n];break;case c.BC:i=[t-r.get(u)/2,n-r.get(a)];break;case c.LC:i=[t,n-r.get(a)/2];break;case c.RC:i=[t-r.get(u),n-r.get(a)/2];break;case c.CC:i=[t-r.get(u)/2,n-r.get(a)/2];break;default:}i&&this.move(i)},_getRegion:function(t){var n;return t?(t=e.Node.one(t),t&&(n=t.get(f))):n=this._posNode.get(l),n},_afterAlignChange:function(e){var t=e.newVal;t&&this._uiSetAlign(t.node,t.points)},_afterAlignOnChange:function(e){this._detachPosAlignUIHandles(),this.get(s)&&this._attachPosAlignUIHandles()}},e.WidgetPositionAlign=c},"3.7.3",{requires:["widget-position"]});
diff --git a/js/yui3/widget-position-constrain/widget-position-constrain-min.js b/js/yui3/widget-position-constrain/widget-position-constrain-min.js
new file mode 100644
index 000000000..2e4112773
--- /dev/null
+++ b/js/yui3/widget-position-constrain/widget-position-constrain-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-position-constrain",function(e,t){function m(t){this._posNode||e.error("WidgetPosition needs to be added to the Widget, before WidgetPositionConstrain is added"),e.after(this._bindUIPosConstrained,this,a)}var n="constrain",r="constrain|xyChange",i="constrainChange",s="preventOverlap",o="align",u="",a="bindUI",f="xy",l="x",c="y",h=e.Node,p="viewportRegion",d="region",v;m.ATTRS={constrain:{value:null,setter:"_setConstrain"},preventOverlap:{value:!1}},v=m._PREVENT_OVERLAP={x:{tltr:1,blbr:1,brbl:1,trtl:1},y:{trbr:1,tlbl:1,bltl:1,brtr:1}},m.prototype={getConstrainedXY:function(e,t){t=t||this.get(n);var r=this._getRegion(t===!0?null:t),i=this._posNode.get(d);return[this._constrain(e[0],l,i,r),this._constrain(e[1],c,i,r)]},constrain:function(e,t){var r,i,s=t||this.get(n);s&&(r=e||this.get(f),i=this.getConstrainedXY(r,s),(i[0]!==r[0]||i[1]!==r[1])&&this.set(f,i,{constrained:!0}))},_setConstrain:function(e){return e===!0?e:h.one(e)},_constrain:function(e,t,n,r){if(r){this.get(s)&&(e=this._preventOverlap(e,t,n,r));var i=t==l,o=i?r.width:r.height,u=i?n.width:n.height,a=i?r.left:r.top,f=i?r.right-u:r.bottom-u;if(e<a||e>f)u<o?e<a?e=a:e>f&&(e=f):e=a}return e},_preventOverlap:function(e,t,n,r){var i=this.get(o),s=t===l,a,f,c,h,p,d;return i&&i.points&&v[t][i.points.join(u)]&&(f=this._getRegion(i.node),f&&(a=s?n.width:n.height,c=s?f.left:f.top,h=s?f.right:f.bottom,p=s?f.left-r.left:f.top-r.top,d=s?r.right-f.right:r.bottom-f.bottom),e>c?d<a&&p>a&&(e=c-a):p<a&&d>a&&(e=h)),e},_bindUIPosConstrained:function(){this.after(i,this._afterConstrainChange),this._enableConstraints(this.get(n))},_afterConstrainChange:function(e){this._enableConstraints(e.newVal)},_enableConstraints:function(e){e?(this.constrain(),this._cxyHandle=this._cxyHandle||this.on(r,this._constrainOnXYChange)):this._cxyHandle&&(this._cxyHandle.detach(),this._cxyHandle=null)},_constrainOnXYChange:function(e){e.constrained||(e.newVal=this.getConstrainedXY(e.newVal))},_getRegion:function(e){var t;return e?(e=h.one(e),e&&(t=e.get(d))):t=this._posNode.get(p),t}},e.WidgetPositionConstrain=m},"3.7.3",{requires:["widget-position"]});
diff --git a/js/yui3/widget-position/widget-position-min.js b/js/yui3/widget-position/widget-position-min.js
new file mode 100644
index 000000000..485bb575d
--- /dev/null
+++ b/js/yui3/widget-position/widget-position-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-position",function(e,t){function d(t){this._posNode=this.get(u),e.after(this._renderUIPosition,this,f),e.after(this._syncUIPosition,this,c),e.after(this._bindUIPosition,this,l)}var n=e.Lang,r=e.Widget,i="xy",s="position",o="positioned",u="boundingBox",a="relative",f="renderUI",l="bindUI",c="syncUI",h=r.UI_SRC,p="xyChange";d.ATTRS={x:{setter:function(e){this._setX(e)},getter:function(){return this._getX()},lazyAdd:!1},y:{setter:function(e){this._setY(e)},getter:function(){return this._getY()},lazyAdd:!1},xy:{value:[0,0],validator:function(e){return this._validateXY(e)}}},d.POSITIONED_CLASS_NAME=r.getClassName(o),d.prototype={_renderUIPosition:function(){this._posNode.addClass(d.POSITIONED_CLASS_NAME)},_syncUIPosition:function(){var e=this._posNode;e.getStyle(s)===a&&this.syncXY(),this._uiSetXY(this.get(i))},_bindUIPosition:function(){this.after(p,this._afterXYChange)},move:function(){var e=arguments,t=n.isArray(e[0])?e[0]:[e[0],e[1]];this.set(i,t)},syncXY:function(){this.set(i,this._posNode.getXY(),{src:h})},_validateXY:function(e){return n.isArray(e)&&n.isNumber(e[0])&&n.isNumber(e[1])},_setX:function(e){this.set(i,[e,this.get(i)[1]])},_setY:function(e){this.set(i,[this.get(i)[0],e])},_getX:function(){return this.get(i)[0]},_getY:function(){return this.get(i)[1]},_afterXYChange:function(e){e.src!=h&&this._uiSetXY(e.newVal)},_uiSetXY:function(e){this._posNode.setXY(e)}},e.WidgetPosition=d},"3.7.3",{requires:["base-build","node-screen","widget"]});
diff --git a/js/yui3/widget-skin/assets/widget-base-core.css b/js/yui3/widget-skin/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-skin/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-skin/widget-skin-min.js b/js/yui3/widget-skin/widget-skin-min.js
new file mode 100644
index 000000000..92d2ce399
--- /dev/null
+++ b/js/yui3/widget-skin/widget-skin-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-skin",function(e,t){var n="boundingBox",r="contentBox",i="skin",s=e.ClassNameManager.getClassName;e.Widget.prototype.getSkinName=function(){var e=this.get(r)||this.get(n),t=new RegExp("\\b"+s(i)+"-(\\S+)"),o;return e&&e.ancestor(function(e){return o=e.get("className").match(t),o}),o?o[1]:null}},"3.7.3",{requires:["widget-base"]});
diff --git a/js/yui3/widget-stack/assets/skins/night/widget-stack.css b/js/yui3/widget-stack/assets/skins/night/widget-stack.css
new file mode 100644
index 000000000..9e3b2e159
--- /dev/null
+++ b/js/yui3/widget-stack/assets/skins/night/widget-stack.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-stacked .yui3-widget-shim{opacity:0;filter:alpha(opacity=0);position:absolute;border:0;top:0;left:0;padding:0;margin:0;z-index:-1;width:100%;height:100%;_width:0;_height:0}#yui3-css-stamp.skin-night-widget-stack{display:none}
diff --git a/js/yui3/widget-stack/assets/skins/sam/widget-stack.css b/js/yui3/widget-stack/assets/skins/sam/widget-stack.css
new file mode 100644
index 000000000..61ac07ba4
--- /dev/null
+++ b/js/yui3/widget-stack/assets/skins/sam/widget-stack.css
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-stacked .yui3-widget-shim{opacity:0;filter:alpha(opacity=0);position:absolute;border:0;top:0;left:0;padding:0;margin:0;z-index:-1;width:100%;height:100%;_width:0;_height:0}#yui3-css-stamp.skin-sam-widget-stack{display:none}
diff --git a/js/yui3/widget-stack/assets/widget-stack-core.css b/js/yui3/widget-stack/assets/widget-stack-core.css
new file mode 100644
index 000000000..c27008606
--- /dev/null
+++ b/js/yui3/widget-stack/assets/widget-stack-core.css
@@ -0,0 +1,25 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-stacked .yui3-widget-shim {
+ opacity:0;
+ filter:alpha(opacity=0);
+ position:absolute;
+ border:none;
+ top:0px;
+ left:0px;
+ padding:0;
+ margin:0;
+ z-index:-1;
+ width:100%;
+ height:100%;
+ /*
+ We'll be setting these programmatically for IE6,
+ to account for cases where height is not set
+ */
+ _width:0;
+ _height:0;
+} \ No newline at end of file
diff --git a/js/yui3/widget-stack/widget-stack-min.js b/js/yui3/widget-stack/widget-stack-min.js
new file mode 100644
index 000000000..e1effcbdd
--- /dev/null
+++ b/js/yui3/widget-stack/widget-stack-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-stack",function(e,t){function O(t){this._stackNode=this.get(f),this._stackHandles={},e.after(this._renderUIStack,this,l),e.after(this._syncUIStack,this,h),e.after(this._bindUIStack,this,c)}var n=e.Lang,r=e.UA,i=e.Node,s=e.Widget,o="zIndex",u="shim",a="visible",f="boundingBox",l="renderUI",c="bindUI",h="syncUI",p="offsetWidth",d="offsetHeight",v="parentNode",m="firstChild",g="ownerDocument",y="width",b="height",w="px",E="shimdeferred",S="shimresize",x="visibleChange",T="widthChange",N="heightChange",C="shimChange",k="zIndexChange",L="contentUpdate",A="stacked";O.ATTRS={shim:{value:r.ie==6},zIndex:{value:0,setter:"_setZIndex"}},O.HTML_PARSER={zIndex:function(e){return this._parseZIndex(e)}},O.SHIM_CLASS_NAME=s.getClassName(u),O.STACKED_CLASS_NAME=s.getClassName(A),O.SHIM_TEMPLATE='<iframe class="'+O.SHIM_CLASS_NAME+'" frameborder="0" title="Widget Stacking Shim" src="javascript:false" tabindex="-1" role="presentation"></iframe>',O.prototype={_syncUIStack:function(){this._uiSetShim(this.get(u)),this._uiSetZIndex(this.get(o))},_bindUIStack:function(){this.after(C,this._afterShimChange),this.after(k,this._afterZIndexChange)},_renderUIStack:function(){this._stackNode.addClass(O.STACKED_CLASS_NAME)},_parseZIndex:function(e){var t;return!e.inDoc()||e.getStyle("position")==="static"?t="auto":t=e.getComputedStyle("zIndex"),t==="auto"?null:t},_setZIndex:function(e){return n.isString(e)&&(e=parseInt(e,10)),n.isNumber(e)||(e=0),e},_afterShimChange:function(e){this._uiSetShim(e.newVal)},_afterZIndexChange:function(e){this._uiSetZIndex(e.newVal)},_uiSetZIndex:function(e){this._stackNode.setStyle(o,e)},_uiSetShim:function(e){e?(this.get(a)?this._renderShim():this._renderShimDeferred(),r.ie==6&&this._addShimResizeHandlers()):this._destroyShim()},_renderShimDeferred:function(){this._stackHandles[E]=this._stackHandles[E]||[];var e=this._stackHandles[E],t=function(e){e.newVal&&this._renderShim()};e.push(this.on(x,t))},_addShimResizeHandlers:function(){this._stackHandles[S]=this._stackHandles[S]||[];var e=this.sizeShim,t=this._stackHandles[S];t.push(this.after(x,e)),t.push(this.after(T,e)),t.push(this.after(N,e)),t.push(this.after(L,e))},_detachStackHandles:function(e){var t=this._stackHandles[e],n;if(t&&t.length>0)while(n=t.pop())n.detach()},_renderShim:function(){var e=this._shimNode,t=this._stackNode;e||(e=this._shimNode=this._getShimTemplate(),t.insertBefore(e,t.get(m)),this._detachStackHandles(E),this.sizeShim())},_destroyShim:function(){this._shimNode&&(this._shimNode.get(v).removeChild(this._shimNode),this._shimNode=null,this._detachStackHandles(E),this._detachStackHandles(S))},sizeShim:function(){var e=this._shimNode,t=this._stackNode;e&&r.ie===6&&this.get(a)&&(e.setStyle(y,t.get(p)+w),e.setStyle(b,t.get(d)+w))},_getShimTemplate:function(){return i.create(O.SHIM_TEMPLATE,this._stackNode.get(g))}},e.WidgetStack=O},"3.7.3",{requires:["base-build","widget"],skinnable:!0});
diff --git a/js/yui3/widget-stdmod/widget-stdmod-min.js b/js/yui3/widget-stdmod/widget-stdmod-min.js
new file mode 100644
index 000000000..c3df420e9
--- /dev/null
+++ b/js/yui3/widget-stdmod/widget-stdmod-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-stdmod",function(e,t){function H(t){this._stdModNode=this.get(w),e.before(this._renderUIStdMod,this,O),e.before(this._bindUIStdMod,this,M),e.before(this._syncUIStdMod,this,_)}var n=e.Lang,r=e.Node,i=e.UA,s=e.Widget,o="",u="hd",a="bd",f="ft",l="header",c="body",h="footer",p="fillHeight",d="stdmod",v="Node",m="Content",g="firstChild",y="childNodes",b="ownerDocument",w="contentBox",E="height",S="offsetHeight",x="auto",T="headerContentChange",N="bodyContentChange",C="footerContentChange",k="fillHeightChange",L="heightChange",A="contentUpdate",O="renderUI",M="bindUI",_="syncUI",D="_applyParsedConfig",P=e.Widget.UI_SRC;H.HEADER=l,H.BODY=c,H.FOOTER=h,H.AFTER="after",H.BEFORE="before",H.REPLACE="replace";var B=H.HEADER,j=H.BODY,F=H.FOOTER,I=B+m,q=F+m,R=j+m;H.ATTRS={headerContent:{value:null},footerContent:{value:null},bodyContent:{value:null},fillHeight:{value:H.BODY,validator:function(e){return this._validateFillHeight(e)}}},H.HTML_PARSER={headerContent:function(e){return this._parseStdModHTML(B)},bodyContent:function(e){return this._parseStdModHTML(j)},footerContent:function(e){return this._parseStdModHTML(F)}},H.SECTION_CLASS_NAMES={header:s.getClassName(u),body:s.getClassName(a),footer:s.getClassName(f)},H.TEMPLATES={header:'<div class="'+H.SECTION_CLASS_NAMES[B]+'"></div>',body:'<div class="'+H.SECTION_CLASS_NAMES[j]+'"></div>',footer:'<div class="'+H.SECTION_CLASS_NAMES[F]+'"></div>'},H.prototype={_syncUIStdMod:function(){var e=this._stdModParsed;(!e||!e[I])&&this._uiSetStdMod(B,this.get(I)),(!e||!e[R])&&this._uiSetStdMod(j,this.get(R)),(!e||!e[q])&&this._uiSetStdMod(F,this.get(q)),this._uiSetFillHeight(this.get(p))},_renderUIStdMod:function(){this._stdModNode.addClass(s.getClassName(d)),this._renderStdModSections(),this.after(T,this._afterHeaderChange),this.after(N,this._afterBodyChange),this.after(C,this._afterFooterChange)},_renderStdModSections:function(){n.isValue(this.get(I))&&this._renderStdMod(B),n.isValue(this.get(R))&&this._renderStdMod(j),n.isValue(this.get(q))&&this._renderStdMod(F)},_bindUIStdMod:function(){this.after(k,this._afterFillHeightChange),this.after(L,this._fillHeight),this.after(A,this._fillHeight)},_afterHeaderChange:function(e){e.src!==P&&this._uiSetStdMod(B,e.newVal,e.stdModPosition)},_afterBodyChange:function(e){e.src!==P&&this._uiSetStdMod(j,e.newVal,e.stdModPosition)},_afterFooterChange:function(e){e.src!==P&&this._uiSetStdMod(F,e.newVal,e.stdModPosition)},_afterFillHeightChange:function(e){this._uiSetFillHeight(e.newVal)},_validateFillHeight:function(e){return!e||e==H.BODY||e==H.HEADER||e==H.FOOTER},_uiSetFillHeight:function(e){var t=this.getStdModNode(e),n=this._currFillNode;n&&t!==n&&n.setStyle(E,o),t&&(this._currFillNode=t),this._fillHeight()},_fillHeight:function(){if(this.get(p)){var e=this.get(E);e!=o&&e!=x&&this.fillHeight(this._currFillNode)}},_uiSetStdMod:function(e,t,r){if(n.isValue(t)){var i=this.getStdModNode(e,!0);this._addStdModContent(i,t,r),this.set(e+m,this._getStdModContent(e),{src:P})}else this._eraseStdMod(e);this.fire(A)},_renderStdMod:function(e){var t=this.get(w),n=this._findStdModSection(e);return n||(n=this._getStdModTemplate(e)),this._insertStdModSection(t,e,n),this[e+v]=n,this[e+v]},_eraseStdMod:function(e){var t=this.getStdModNode(e);t&&(t.remove(!0),delete this[e+v])},_insertStdModSection:function(e,t,n){var r=e.get(g);if(t===F||!r)e.appendChild(n);else if(t===B)e.insertBefore(n,r);else{var i=this[F+v];i?e.insertBefore(n,i):e.appendChild(n)}},_getStdModTemplate:function(e){return r.create(H.TEMPLATES[e],this._stdModNode.get(b))},_addStdModContent:function(e,t,n){switch(n){case H.BEFORE:n=0;break;case H.AFTER:n=undefined;break;default:n=H.REPLACE}e.insert(t,n)},_getPreciseHeight:function(e){var t=e?e.get(S):0,n="getBoundingClientRect";if(e&&e.hasMethod(n)){var r=e.invoke(n);r&&(t=r.bottom-r.top)}return t},_findStdModSection:function(e){return this.get(w).one("> ."+H.SECTION_CLASS_NAMES[e])},_parseStdModHTML:function(t){var n=this._findStdModSection(t);return n?(this._stdModParsed||(this._stdModParsed={},e.before(this._applyStdModParsedConfig,this,D)),this._stdModParsed[t+m]=1,n.get("innerHTML")):null},_applyStdModParsedConfig:function(e,t,n){var r=this._stdModParsed;r&&(r[I]=!(I in t)&&I in r,r[R]=!(R in t)&&R in r,r[q]=!(q in t)&&q in r)},_getStdModContent:function(e){return this[e+v]?this[e+v].get(y):null},setStdModContent:function(e,t,n){this.set(e+m,t,{stdModPosition:n})},getStdModNode:function(e,t){var n=this[e+v]||null;return!n&&t&&(n=this._renderStdMod(e)),n},fillHeight:function(e){if(e){var t=this.get(w),r=[this.headerNode,this.bodyNode,this.footerNode],s,o,u=0,a=0,f=!1;for(var l=0,c=r.length;l<c;l++)s=r[l],s&&(s!==e?u+=this._getPreciseHeight(s):f=!0);f&&((i.ie||i.opera)&&e.set(S,0),o=t.get(S)-parseInt(t.getComputedStyle("paddingTop"),10)-parseInt(t.getComputedStyle("paddingBottom"),10)-parseInt(t.getComputedStyle("borderBottomWidth"),10)-parseInt(t.getComputedStyle("borderTopWidth"),10),n.isNumber(o)&&(a=o-u,a>=0&&e.set(S,a)))}}},e.WidgetStdMod=H},"3.7.3",{requires:["base-build","widget"]});
diff --git a/js/yui3/widget-uievents/assets/widget-base-core.css b/js/yui3/widget-uievents/assets/widget-base-core.css
new file mode 100644
index 000000000..9e5ce67a6
--- /dev/null
+++ b/js/yui3/widget-uievents/assets/widget-base-core.css
@@ -0,0 +1,26 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+.yui3-widget-hidden {
+ display:none;
+}
+
+.yui3-widget-content {
+ overflow:hidden;
+}
+
+.yui3-widget-content-expanded {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing:border-box;
+ height:100%;
+}
+
+/* Only used for IE6, to go from a bigger size to a smaller size when using cb.sizeTo(bb) */
+.yui3-widget-tmp-forcesize {
+ overflow:hidden !important;
+} \ No newline at end of file
diff --git a/js/yui3/widget-uievents/widget-uievents-min.js b/js/yui3/widget-uievents/widget-uievents-min.js
new file mode 100644
index 000000000..ad9fb61b0
--- /dev/null
+++ b/js/yui3/widget-uievents/widget-uievents-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("widget-uievents",function(e,t){var n="boundingBox",r=e.Widget,i="render",s=e.Lang,o=":",u=e.Widget._uievts=e.Widget._uievts||{};e.mix(r.prototype,{_destroyUIEvents:function(){var t=e.stamp(this,!0);e.each(u,function(n,r){n.instances[t]&&(delete n.instances[t],e.Object.isEmpty(n.instances)&&(n.handle.detach(),u[r]&&delete u[r]))})},UI_EVENTS:e.Node.DOM_EVENTS,_getUIEventNode:function(){return this.get(n)},_createUIEvent:function(t){var n=this._getUIEventNode(),i=e.stamp(n)+t,s=u[i],o;s||(o=n.delegate(t,function(e){var t=r.getByNode(this);t&&t._filterUIEvent(e)&&t.fire(e.type,{domEvent:e})},"."+e.Widget.getClassName()),u[i]=s={instances:{},handle:o}),s.instances[e.stamp(this)]=1},_filterUIEvent:function(e){return e.currentTarget.compareTo(e.container)||e.container.compareTo(this._getUIEventNode())},_getUIEvent:function(e){if(s.isString(e)){var t=this.parseType(e)[1],n,r;return t&&(n=t.indexOf(o),n>-1&&(t=t.substring(n+o.length)),this.UI_EVENTS[t]&&(r=t)),r}},_initUIEvent:function(e){var t=this._getUIEvent(e),n=this._uiEvtsInitQueue||{};t&&!n[t]&&(this._uiEvtsInitQueue=n[t]=1,this.after(i,function(){this._createUIEvent(t),delete this._uiEvtsInitQueue[t]}))},on:function(e){return this._initUIEvent(e),r.superclass.on.apply(this,arguments)},publish:function(e,t){var n=this._getUIEvent(e);return n&&t&&t.defaultFn&&this._initUIEvent(n),r.superclass.publish.apply(this,arguments)}},!0)},"3.7.3",{requires:["node-event-delegate","widget-base"]});
diff --git a/js/yui3/yql-nodejs/yql-nodejs-min.js b/js/yui3/yql-nodejs/yql-nodejs-min.js
new file mode 100644
index 000000000..a4ce77547
--- /dev/null
+++ b/js/yui3/yql-nodejs/yql-nodejs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yql-nodejs",function(e,t){var n=require("request");e.YQLRequest.prototype._send=function(e,t){n(e,{method:"GET",timeout:t.timeout||3e4},function(e,n){e?t.on.success({error:e}):t.on.success(JSON.parse(n.body))})}},"3.7.3");
diff --git a/js/yui3/yql-winjs/yql-winjs-min.js b/js/yui3/yql-winjs/yql-winjs-min.js
new file mode 100644
index 000000000..be00d60a8
--- /dev/null
+++ b/js/yui3/yql-winjs/yql-winjs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yql-winjs",function(e,t){e.YQLRequest.prototype._send=function(e,t){var n=new XMLHttpRequest,r;n.open("GET",e,!0),n.onreadystatechange=function(){n.readyState===4&&(clearTimeout(r),t.on.success(JSON.parse(n.responseText)))},n.send(),r=setTimeout(function(){n.abort(),t.on.timeout("script timeout")},t.timeout||3e4)}},"3.7.3");
diff --git a/js/yui3/yql/yql-min.js b/js/yui3/yql/yql-min.js
new file mode 100644
index 000000000..b764a5071
--- /dev/null
+++ b/js/yui3/yql/yql-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yql",function(e,t){var n=function(t,n,r,i){r||(r={}),r.q=t,r.format||(r.format=e.YQLRequest.FORMAT),r.env||(r.env=e.YQLRequest.ENV),this._context=this,i&&i.context&&(this._context=i.context,delete i.context),r&&r.context&&(this._context=r.context,delete r.context),this._params=r,this._opts=i,this._callback=n};n.prototype={_jsonp:null,_opts:null,_callback:null,_params:null,_context:null,_internal:function(){this._callback.apply(this._context,arguments)},send:function(){var t=[],n=this._opts&&this._opts.proto?this._opts.proto:e.YQLRequest.PROTO,r;return e.each(this._params,function(e,n){t.push(n+"="+encodeURIComponent(e))}),t=t.join("&"),n+=(this._opts&&this._opts.base?this._opts.base:e.YQLRequest.BASE_URL)+t,r=e.Lang.isFunction(this._callback)?{on:{success:this._callback}}:this._callback,r.on=r.on||{},this._callback=r.on.success,r.on.success=e.bind(this._internal,this),this._send(n,r),this},_send:function(t,n){n.allowCache!==!1&&(n.allowCache=!0),this._jsonp?(this._jsonp.url=t,n.on&&n.on.success&&(this._jsonp._config.on.success=n.on.success),this._jsonp.send()):this._jsonp=e.jsonp(t,n)}},n.FORMAT="json",n.PROTO="http",n.BASE_URL="://query.yahooapis.com/v1/public/yql?",n.ENV="http://datatables.org/alltables.env",e.YQLRequest=n,e.YQL=function(t,n,r,i){return(new e.YQLRequest(t,n,r,i)).send()}},"3.7.3",{requires:["jsonp","jsonp-url"]});
diff --git a/js/yui3/yui-base/yui-base-min.js b/js/yui3/yui-base/yui-base-min.js
new file mode 100644
index 000000000..683b45a7e
--- /dev/null
+++ b/js/yui3/yui-base/yui-base-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+typeof YUI!="undefined"&&(YUI._YUI=YUI);var YUI=function(){var e=0,t=this,n=arguments,r=n.length,i=function(e,t){return e&&e.hasOwnProperty&&e instanceof t},s=typeof YUI_config!="undefined"&&YUI_config;i(t,YUI)?(t._init(),YUI.GlobalConfig&&t.applyConfig(YUI.GlobalConfig),s&&t.applyConfig(s),r||t._setup()):t=new YUI;if(r){for(;e<r;e++)t.applyConfig(n[e]);t._setup()}return t.instanceOf=i,t};(function(){var e,t,n="3.7.3",r=".",i="http://yui.yahooapis.com/",s="yui3-js-enabled",o="yui3-css-stamp",u=function(){},a=Array.prototype.slice,f={"io.xdrReady":1,"io.xdrResponse":1,"SWF.eventHandler":1},l=typeof window!="undefined",c=l?window:null,h=l?c.document:null,p=h&&h.documentElement,d=p&&p.className,v={},m=(new Date).getTime(),g=function(e,t,n,r){e&&e.addEventListener?e.addEventListener(t,n,r):e&&e.attachEvent&&e.attachEvent("on"+t,n)},y=function(e,t,n,r){if(e&&e.removeEventListener)try{e.removeEventListener(t,n,r)}catch(i){}else e&&e.detachEvent&&e.detachEvent("on"+t,n)},b=function(){YUI.Env.windowLoaded=!0,YUI.Env.DOMReady=!0,l&&y(window,"load",b)},w=function(e,t){var n=e.Env._loader,r=["loader-base"],i=YUI.Env,s=i.mods;return n?(n.ignoreRegistered=!1,n.onEnd=null,n.data=null,n.required=[],n.loadType=null):(n=new e.Loader(e.config),e.Env._loader=n),s&&s.loader&&(r=[].concat(r,YUI.Env.loaderExtras)),YUI.Env.core=e.Array.dedupe([].concat(YUI.Env.core,r)),n},E=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},S={success:!0};p&&d.indexOf(s)==-1&&(d&&(d+=" "),d+=s,p.className=d),n.indexOf("@")>-1&&(n="3.5.0"),e={applyConfig:function(e){e=e||u;var t,n,r=this.config,i=r.modules,s=r.groups,o=r.aliases,a=this.Env._loader;for(n in e)e.hasOwnProperty(n)&&(t=e[n],i&&n=="modules"?E(i,t):o&&n=="aliases"?E(o,t):s&&n=="groups"?E(s,t):n=="win"?(r[n]=t&&t.contentWindow||t,r.doc=r[n]?r[n].document:null):n!="_yuid"&&(r[n]=t));a&&a._config(e)},_config:function(e){this.applyConfig(e)},_init:function(){var e,t,r=this,s=YUI.Env,u=r.Env,a;r.version=n;if(!u){r.Env={core:["get","features","intl-base","yui-log","yui-later"],loaderExtras:["loader-rollup","loader-yui3"],mods:{},versions:{},base:i,cdn:i+n+"/build/",_idx:0,_used:{},_attached:{},_missed:[],_yidx:0,_uidx:0,_guidp:"y",_loaded:{},_BASE_RE:/(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,parseBasePath:function(e,t){var n=e.match(t),r,i;return n&&(r=RegExp.leftContext||e.slice(0,e.indexOf(n[0])),i=n[3],n[1]&&(r+="?"+n[1]),r={filter:i,path:r}),r},getBase:s&&s.getBase||function(t){var n=h&&h.getElementsByTagName("script")||[],i=u.cdn,s,o,a,f;for(o=0,a=n.length;o<a;++o){f=n[o].src;if(f){s=r.Env.parseBasePath(f,t);if(s){e=s.filter,i=s.path;break}}}return i}},u=r.Env,u._loaded[n]={};if(s&&r!==YUI)u._yidx=++s._yidx,u._guidp=("yui_"+n+"_"+u._yidx+"_"+m).replace(/\./g,"_").replace(/-/g,"_");else if(YUI._YUI){s=YUI._YUI.Env,u._yidx+=s._yidx,u._uidx+=s._uidx;for(a in s)a in u||(u[a]=s[a]);delete YUI._YUI}r.id=r.stamp(r),v[r.id]=r}r.constructor=YUI,r.config=r.config||{bootstrap:!0,cacheUse:!0,debug:!0,doc:h,fetchCSS:!0,throwFail:!0,useBrowserConsole:!0,useNativeES5:!0,win:c},h&&!h.getElementById(o)&&(t=h.createElement("div"),t.innerHTML='<div id="'+o+'" style="position: absolute !important; visibility: hidden !important"></div>',YUI.Env.cssStampEl=t.firstChild,h.body?h.body.appendChild(YUI.Env.cssStampEl):p.insertBefore(YUI.Env.cssStampEl,p.firstChild)),r.config.lang=r.config.lang||"en-US",r.config.base=YUI.config.base||r.Env.getBase(r.Env._BASE_RE);if(!e||!"mindebug".indexOf(e))e="min";e=e?"-"+e:e,r.config.loaderPath=YUI.config.loaderPath||"loader/loader"+e+".js"},_setup:function(e){var t,n=this,r=[],i=YUI.Env.mods,s=n.config.core||[].concat(YUI.Env.core);for(t=0;t<s.length;t++)i[s[t]]&&r.push(s[t]);n._attach(["yui-base"]),n._attach(r),n.Loader&&w(n)},applyTo:function(e,t,n){if(t in f){var r=v[e],i,s,o;if(r){i=t.split("."),s=r;for(o=0;o<i.length;o+=1)s=s[i[o]],s||this.log("applyTo not found: "+t,"warn","yui");return s&&s.apply(r,n)}return null}return this.log(t+": applyTo not allowed","warn","yui"),null},add:function(e,t,n,r){r=r||{};var i=YUI.Env,s={name:e,fn:t,version:n,details:r},o={},u,a,f,l=i.versions;i.mods[e]=s,l[n]=l[n]||{},l[n][e]=s;for(f in v)v.hasOwnProperty(f)&&(a=v[f],o[a.id]||(o[a.id]=!0,u=a.Env._loader,u&&(!u.moduleInfo[e]||u.moduleInfo[e].temp)&&u.addModule(r,e)));return this},_attach:function(e,t){var n,r,i,s,o,u,a,f=YUI.Env.mods,l=YUI.Env.aliases,c=this,h,p=YUI.Env._renderedMods,d=c.Env._loader,v=c.Env._attached,m=e.length,d,g,y,b=[];for(n=0;n<m;n++){r=e[n],i=f[r],b.push(r);if(d&&d.conditions[r])for(h in d.conditions[r])d.conditions[r].hasOwnProperty(h)&&(g=d.conditions[r][h],y=g&&(g.ua&&c.UA[g.ua]||g.test&&g.test(c)),y&&b.push(g.name))}e=b,m=e.length;for(n=0;n<m;n++)if(!v[e[n]]){r=e[n],i=f[r];if(l&&l[r]&&!i){c._attach(l[r]);continue}if(!i)d&&d.moduleInfo[r]&&(i=d.moduleInfo[r],t=!0),!t&&r&&r.indexOf("skin-")===-1&&r.indexOf("css")===-1&&(c.Env._missed.push(r),c.Env._missed=c.Array.dedupe(c.Env._missed),c.message("NOT loaded: "+r,"warn","yui"));else{v[r]=!0;for(h=0;h<c.Env._missed.length;h++)c.Env._missed[h]===r&&(c.message("Found: "+r+" (was reported as missing earlier)","warn","yui"),c.Env._missed.splice(h,1));if(d&&p&&p[r]&&p[r].temp){d.getRequires(p[r]),o=[];for(h in d.moduleInfo[r].expanded_map)d.moduleInfo[r].expanded_map.hasOwnProperty(h)&&o.push(h);c._attach(o)}s=i.details,o=s.requires,u=s.use,a=s.after,s.lang&&(o=o||[],o.unshift("intl"));if(o)for(h=0;h<o.length;h++)if(!v[o[h]]){if(!c._attach(o))return!1;break}if(a)for(h=0;h<a.length;h++)if(!v[a[h]]){if(!c._attach(a,!0))return!1;break}if(i.fn)if(c.config.throwFail)i.fn(c,r);else try{i.fn(c,r)}catch(w){return c.error("Attach error: "+r,w,r),!1}if(u)for(h=0;h<u.length;h++)if(!v[u[h]]){if(!c._attach(u))return!1;break}}}return!0},_delayCallback:function(e,t){var n=this,r=["event-base"];return t=n.Lang.isObject(t)?t:{event:t},t.event==="load"&&r.push("event-synthetic"),function(){var i=arguments;n._use(r,function(){n.on(t.event,function(){i[1].delayUntil=t.event,e.apply(n,i)},t.args)})}},use:function(){var e=a.call(arguments,0),t=e[e.length-1],n=this,r=0,i=[],s,o=n.Env,u=!0;n.Lang.isFunction(t)?(e.pop(),n.config.delayUntil&&(t=n._delayCallback(t,n.config.delayUntil))):t=null,n.Lang.isArray(e[0])&&(e=e[0]);if(n.config.cacheUse){while(s=e[r++])if(!o._attached[s]){u=!1;break}if(u)return e.length,n._notify(t,S,e),n}return n._loading?(n._useQueue=n._useQueue||new n.Queue,n._useQueue.add([e,t])):n._use(e,function(n,r){n._notify(t,r,e)}),n},_notify:function(e,t,n){if(!t.success&&this.config.loadErrorFn)this.config.loadErrorFn.call(this,this,e,t,n);else if(e){this.Env._missed&&this.Env._missed.length&&(t.msg="Missing modules: "+this.Env._missed.join(),t.success=!1);if(this.config.throwFail)e(this,t);else try{e(this,t)}catch(r){this.error("use callback error",r,n)}}},_use:function(e,t){this.Array||this._attach(["yui-base"]);var r,i,s,o,u=this,a=YUI.Env,f=a.mods,l=u.Env,c=l._used,h=a.aliases,p=a._loaderQueue,d=e[0],v=u.Array,m=u.config,g=m.bootstrap,y=[],b,E=[],S=!0,x=m.fetchCSS,T=function(e,t){var r=0,i=[],s,o,u,l,p;if(!e.length)return;if(h){o=e.length;for(r=0;r<o;r++)h[e[r]]&&!f[e[r]]?i=[].concat(i,h[e[r]]):i.push(e[r]);e=i}o=e.length;for(r=0;r<o;r++){s=e[r],t||E.push(s);if(c[s])continue;u=f[s],l=null,p=null,u?(c[s]=!0,l=u.details.requires,p=u.details.use):a._loaded[n][s]?c[s]=!0:y.push(s),l&&l.length&&T(l),p&&p.length&&T(p,1)}},N=function(n){var r=n||{success:!0,msg:"not dynamic"},i,s,o=!0,a=r.data;u._loading=!1,a&&(s=y,y=[],E=[],T(a),i=y.length,i&&[].concat(y).sort().join()==s.sort().join()&&(i=!1)),i&&a?(u._loading=!0,u._use(y,function(){u._attach(a)&&u._notify(t,r,a)})):(a&&(o=u._attach(a)),o&&u._notify(t,r,e)),u._useQueue&&u._useQueue.size()&&!u._loading&&u._use.apply(u,u._useQueue.next())};if(d==="*"){e=[];for(b in f)f.hasOwnProperty(b)&&e.push(b);return S=u._attach(e),S&&N(),u}return(f.loader||f["loader-base"])&&!u.Loader&&u._attach(["loader"+(f.loader?"":"-base")]),g&&u.Loader&&e.length&&(i=w(u),i.require(e),i.ignoreRegistered=!0,i._boot=!0,i.calculate(null,x?null:"js"),e=i.sorted,i._boot=!1),T(e),r=y.length,r&&(y=v.dedupe(y),r=y.length),g&&r&&u.Loader?(u._loading=!0,i=w(u),i.onEnd=N,i.context=u,i.data=e,i.ignoreRegistered=!1,i.require(e),i.insert(null,x?null:"js")):g&&r&&u.Get&&!l.bootstrapped?(u._loading=!0,s=function(){u._loading=!1,p.running=!1,l.bootstrapped=!0,a._bootstrapping=!1,u._attach(["loader"])&&u._use(e,t)},a._bootstrapping?p.add(s):(a._bootstrapping=!0,u.Get.script(m.base+m.loaderPath,{onEnd:s}))):(S=u._attach(e),S&&N()),u},namespace:function(){var e=arguments,t,n=0,i,s,o;for(;n<e.length;n++){t=this,o=e[n];if(o.indexOf(r)>-1){s=o.split(r);for(i=s[0]=="YAHOO"?1:0;i<s.length;i++)t[s[i]]=t[s[i]]||{},t=t[s[i]]}else t[o]=t[o]||{},t=t[o]}return t},log:u,message:u,dump:function(e){return""+e},error:function(e,t,n){var r=this,i;r.config.errorFn&&(i=r.config.errorFn.apply(r,arguments));if(!i)throw t||new Error(e);return r.message(e,"error",""+n),r},guid:function(e){var t=this.Env._guidp+"_"+ ++this.Env._uidx;return e?e+t:t},stamp:function(e,t){var n;if(!e)return e;e.uniqueID&&e.nodeType&&e.nodeType!==9?n=e.uniqueID:n=typeof e=="string"?e:e._yuid;if(!n){n=this.guid();if(!t)try{e._yuid=n}catch(r){n=null}}return n},destroy:function(){var e=this;e.Event&&e.Event._unload(),delete v[e.id],delete e.Env,delete e.config}},YUI.prototype=e;for(t in e)e.hasOwnProperty(t)&&(YUI[t]=e[t]);YUI.applyConfig=function(e){if(!e)return;YUI.GlobalConfig&&this.prototype.applyConfig.call(this,YUI.GlobalConfig),this.prototype.applyConfig.call(this,e),YUI.GlobalConfig=this.config},YUI._init(),l?g(window,"load",b):b(),YUI.Env.add=g,YUI.Env.remove=y,typeof exports=="object"&&(exports.YUI=YUI)})(),YUI.add("yui-base",function(e,t){function h(e,t,n){var r,i;t||(t=0);if(n||h.test(e))try{return l.slice.call(e,t)}catch(s){i=[];for(r=e.length;t<r;++t)i.push(e[t]);return i}return[e]}function p(){this._init(),this.add.apply(this,arguments)}var n=e.Lang||(e.Lang={}),r=String.prototype,i=Object.prototype.toString,s={"undefined":"undefined",number:"number","boolean":"boolean",string:"string","[object Function]":"function","[object RegExp]":"regexp","[object Array]":"array","[object Date]":"date","[object Error]":"error"},o=/\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,u=/^\s+|\s+$/g,a=/\{\s*\[(?:native code|function)\]\s*\}/i;n._isNative=function(t){return!!(e.config.useNativeES5&&t&&a.test(t))},n.isArray=n._isNative(Array.isArray)?Array.isArray:function(e){return n.type(e)==="array"},n.isBoolean=function(e){return typeof e=="boolean"},n.isDate=function(e){return n.type(e)==="date"&&e.toString()!=="Invalid Date"&&!isNaN(e)},n.isFunction=function(e){return n.type(e)==="function"},n.isNull=function(e){return e===null},n.isNumber=function(e){return typeof e=="number"&&isFinite(e)},n.isObject=function(e,t){var r=typeof e;return e&&(r==="object"||!t&&(r==="function"||n.isFunction(e)))||!1},n.isString=function(e){return typeof e=="string"},n.isUndefined=function(e){return typeof e=="undefined"},n.isValue=function(e){var t=n.type(e);switch(t){case"number":return isFinite(e);case"null":case"undefined":return!1;default:return!!t}},n.now=Date.now||function(){return(new Date).getTime()},n.sub=function(e,t){return e.replace?e.replace(o,function(e,r){return n.isUndefined(t[r])?e:t[r]}):e},n.trim=r.trim?function(e){return e&&e.trim?e.trim():e}:function(e){try{return e.replace(u,"")}catch(t){return e}},n.trimLeft=r.trimLeft?function(e){return e.trimLeft()}:function(e){return e.replace(/^\s+/,"")},n.trimRight=r.trimRight?function(e){return e.trimRight()}:function(e){return e.replace(/\s+$/,"")},n.type=function(e){return s[typeof e]||s[i.call(e)]||(e?"object":"null")};var f=e.Lang,l=Array.prototype,c=Object.prototype.hasOwnProperty;e.Array=h,h.dedupe=function(e){var t={},n=[],r,i,s;for(r=0,s=e.length;r<s;++r)i=e[r],c.call(t,i)||(t[i]=1,n.push(i));return n},h.each=h.forEach=f._isNative(l.forEach)?function(t,n,r){return l.forEach.call(t||[],n,r||e),e}:function(t,n,r){for(var i=0,s=t&&t.length||0;i<s;++i)i in t&&n.call(r||e,t[i],i,t);return e},h.hash=function(e,t){var n={},r=t&&t.length||0,i,s;for(i=0,s=e.length;i<s;++i)i in e&&(n[e[i]]=r>i&&i in t?t[i]:!0);return n},h.indexOf=f._isNative(l.indexOf)?function(e,t,n){return l.indexOf.call(e,t,n)}:function(e,t,n){var r=e.length;n=+n||0,n=(n>0||-1)*Math.floor(Math.abs(n)),n<0&&(n+=r,n<0&&(n=0));for(;n<r;++n)if(n in e&&e[n]===t)return n;return-1},h.numericSort=function(e,t){return e-t},h.some=f._isNative(l.some)?function(e,t,n){return l.some.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&t.call(n,e[r],r,e))return!0;return!1},h.test=function(e){var t=0;if(f.isArray(e))t=1;else if(f.isObject(e))try{"length"in e&&!e.tagName&&(!e.scrollTo||!e.document)&&!e.apply&&(t=2)}catch(n){}return t},p.prototype={_init:function(){this._q=[]},next:function(){return this._q.shift()},last:function(){return this._q.pop()},add:function(){return this._q.push.apply(this._q,arguments),this},size:function(){return this._q.length}},e.Queue=p,YUI.Env._loaderQueue=YUI.Env._loaderQueue||new p;var d="__",c=Object.prototype.hasOwnProperty,v=e.Lang.isObject;e.cached=function(e,t,n){return t||(t={}),function(r){var i=arguments.length>1?Array.prototype.join.call(arguments,d):String(r);if(!(i in t)||n&&t[i]==n)t[i]=e.apply(e,arguments);return t[i]}},e.getLocation=function(){var t=e.config.win;return t&&t.location},e.merge=function(){var e=0,t=arguments.length,n={},r,i;for(;e<t;++e){i=arguments[e];for(r in i)c.call(i,r)&&(n[r]=i[r])}return n},e.mix=function(t,n,r,i,s,o){var u,a,f,l,h,p,d;if(!t||!n)return t||e;if(s){s===2&&e.mix(t.prototype,n.prototype,r,i,0,o),f=s===1||s===3?n.prototype:n,d=s===1||s===4?t.prototype:t;if(!f||!d)return t}else f=n,d=t;u=r&&!o;if(i)for(l=0,p=i.length;l<p;++l){h=i[l];if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}else{for(h in f){if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}e.Object._hasEnumBug&&e.mix(d,f,r,e.Object._forceEnum,s,o)}return t};var f=e.Lang,c=Object.prototype.hasOwnProperty,m,g=e.Object=f._isNative(Object.create)?function(e){return Object.create(e)}:function(){function e(){}return function(t){return e.prototype=t,new e}}(),y=g._forceEnum=["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf"],b=g._hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),w=g._hasProtoEnumBug=function(){}.propertyIsEnumerable("prototype"),E=g.owns=function(e,t){return!!e&&c.call(e,t)};g.hasKey=E,g.keys=f._isNative(Object.keys)?Object.keys:function(e){if(!f.isObject(e))throw new TypeError("Object.keys called on a non-object");var t=[],n,r,i;if(w&&typeof e=="function")for(r in e)E(e,r)&&r!=="prototype"&&t.push(r);else for(r in e)E(e,r)&&t.push(r);if(b)for(n=0,i=y.length;n<i;++n)r=y[n],E(e,r)&&t.push(r);return t},g.values=function(e){var t=g.keys(e),n=0,r=t.length,i=[];for(;n<r;++n)i.push(e[t[n]]);return i},g.size=function(e){try{return g.keys(e).length}catch(t){return 0}},g.hasValue=function(t,n){return e.Array.indexOf(g.values(t),n)>-1},g.each=function(t,n,r,i){var s;for(s in t)(i||E(t,s))&&n.call(r||e,t[s],s,t);return e},g.some=function(t,n,r,i){var s;for(s in t)if(i||E(t,s))if(n.call(r||e,t[s],s,t))return!0;return!1},g.getValue=function(t,n){if(!f.isObject(t))return m;var r,i=e.Array(n),s=i.length;for(r=0;t!==m&&r<s;r++)t=t[i[r]];return t},g.setValue=function(t,n,r){var i,s=e.Array(n),o=s.length-1,u=t;if(o>=0){for(i=0;u!==m&&i<o;i++)u=u[s[i]];if(u===m)return m;u[s[i]]=r}return t},g.isEmpty=function(e){return!g.keys(Object(e)).length},YUI.Env.parseUA=function(t){var n=function(e){var t=0;return parseFloat(e.replace(/\./g,function(){return t++===1?"":"."}))},r=e.config.win,i=r&&r.navigator,s={ie:0,opera:0,gecko:0,webkit:0,safari:0,chrome:0,mobile:null,air:0,phantomjs:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,silk:0,accel:!1,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null,nodejs:0,winjs:typeof Windows!="undefined"&&!!Windows.System,touchEnabled:!1},o=t||i&&i.userAgent,u=r&&r.location,a=u&&u.href,f;return s.userAgent=o,s.secure=a&&a.toLowerCase().indexOf("https")===0,o&&(/windows|win32/i.test(o)?s.os="windows":/macintosh|mac_powerpc/i.test(o)?s.os="macintosh":/android/i.test(o)?s.os="android":/symbos/i.test(o)?s.os="symbos":/linux/i.test(o)?s.os="linux":/rhino/i.test(o)&&(s.os="rhino"),/KHTML/.test(o)&&(s.webkit=1),/IEMobile|XBLWP7/.test(o)&&(s.mobile="windows"),/Fennec/.test(o)&&(s.mobile="gecko"),f=o.match(/AppleWebKit\/([^\s]*)/),f&&f[1]&&(s.webkit=n(f[1]),s.safari=s.webkit,/PhantomJS/.test(o)&&(f=o.match(/PhantomJS\/([^\s]*)/),f&&f[1]&&(s.phantomjs=n(f[1]))),/ Mobile\//.test(o)||/iPad|iPod|iPhone/.test(o)?(s.mobile="Apple",f=o.match(/OS ([^\s]*)/),f&&f[1]&&(f=n(f[1].replace("_","."))),s.ios=f,s.os="ios",s.ipad=s.ipod=s.iphone=0,f=o.match(/iPad|iPod|iPhone/),f&&f[0]&&(s[f[0].toLowerCase()]=s.ios)):(f=o.match(/NokiaN[^\/]*|webOS\/\d\.\d/),f&&(s.mobile=f[0]),/webOS/.test(o)&&(s.mobile="WebOS",f=o.match(/webOS\/([^\s]*);/),f&&f[1]&&(s.webos=n(f[1]))),/ Android/.test(o)&&(/Mobile/.test(o)&&(s.mobile="Android"),f=o.match(/Android ([^\s]*);/),f&&f[1]&&(s.android=n(f[1]))),/Silk/.test(o)&&(f=o.match(/Silk\/([^\s]*)\)/),f&&f[1]&&(s.silk=n(f[1])),s.android||(s.android=2.34,s.os="Android"),/Accelerated=true/.test(o)&&(s.accel=!0))),f=o.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/),f&&f[1]&&f[2]?(s.chrome=n(f[2]),s.safari=0,f[1]==="CrMo"&&(s.mobile="chrome")):(f=o.match(/AdobeAIR\/([^\s]*)/),f&&(s.air=f[0]))),s.webkit||(/Opera/.test(o)?(f=o.match(/Opera[\s\/]([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),f=o.match(/Version\/([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),/Opera Mobi/.test(o)&&(s.mobile="opera",f=o.replace("Opera Mobi","").match(/Opera ([^\s]*)/),f&&f[1]&&(s.opera=n(f[1]))),f=o.match(/Opera Mini[^;]*/),f&&(s.mobile=f[0])):(f=o.match(/MSIE\s([^;]*)/),f&&f[1]?s.ie=n(f[1]):(f=o.match(/Gecko\/([^\s]*)/),f&&(s.gecko=1,f=o.match(/rv:([^\s\)]*)/),f&&f[1]&&(s.gecko=n(f[1]))))))),r&&i&&!(s.chrome&&s.chrome<6)&&(s.touchEnabled="ontouchstart"in r||"msMaxTouchPoints"in i&&i.msMaxTouchPoints>0),t||(typeof process=="object"&&process.versions&&process.versions.node&&(s.os=process.platform,s.nodejs=n(process.versions.node)),YUI.Env.UA=s),s},e.UA=YUI.Env.UA||YUI.Env.parseUA(),e.UA.compareVersions=function(e,t){var n,r,i,s,o,u;if(e===t)return 0;r=(e+"").split("."),s=(t+"").split(".");for(o=0,u=Math.max(r.length,s.length);o<u;++o){n=parseInt(r[o],10),i=parseInt(s[o],10),isNaN(n)&&(n=0),isNaN(i)&&(i=0);if(n<i)return-1;if(n>i)return 1}return 0},YUI.Env.aliases={anim:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],"anim-shape-transform":["anim-shape"],app:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],attribute:["attribute-base","attribute-complex"],autocomplete:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],base:["base-base","base-pluginhost","base-build"],cache:["cache-base","cache-offline","cache-plugin"],collection:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],controller:["router"],dataschema:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],datasource:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],datatable:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],"datatable-deprecated":["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],datatype:["datatype-date","datatype-number","datatype-xml"],"datatype-date":["datatype-date-parse","datatype-date-format","datatype-date-math"],"datatype-number":["datatype-number-parse","datatype-number-format"],"datatype-xml":["datatype-xml-parse","datatype-xml-format"],dd:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],dom:["dom-base","dom-screen","dom-style","selector-native","selector"],editor:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],event:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],"event-custom":["event-custom-base","event-custom-complex"],"event-gestures":["event-flick","event-move"],handlebars:["handlebars-compiler"],highlight:["highlight-base","highlight-accentfold"],history:["history-base","history-hash","history-hash-ie","history-html5"],io:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],json:["json-parse","json-stringify"],loader:["loader-base","loader-rollup","loader-yui3"],node:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],pluginhost:["pluginhost-base","pluginhost-config"],querystring:["querystring-parse","querystring-stringify"],recordset:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],resize:["resize-base","resize-proxy","resize-constrain"],slider:["slider-base","slider-value-range","clickable-rail","range-slider"],text:["text-accentfold","text-wordbreak"],widget:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]}},"3.7.3",{use:["get","features","intl-base","yui-log","yui-later"]}),YUI.add("get",function(e,t){var n=e.Lang,r,i,s;e.Get=i={cssOptions:{attributes:{rel:"stylesheet"},doc:e.config.linkDoc||e.config.doc,pollInterval:50},jsOptions:{autopurge:!0,doc:e.config.scriptDoc||e.config.doc},options:{attributes:{charset:"utf-8"},purgethreshold:20},REGEX_CSS:/\.css(?:[?;].*)?$/i,REGEX_JS:/\.js(?:[?;].*)?$/i,_insertCache:{},_pending:null,_purgeNodes:[],_queue:[],abort:function(e){var t,n,r,i,s;if(!e.abort){n=e,s=this._pending,e=null;if(s&&s.transaction.id===n)e=s.transaction,this._pending=null;else for(t=0,i=this._queue.length;t<i;++t){r=this._queue[t].transaction;if(r.id===n){e=r,this._queue.splice(t,1);break}}}e&&e.abort()},css:function(e,t,n){return this._load("css",e,t,n)},js:function(e,t,n){return this._load("js",e,t,n)},load:function(e,t,n){return this._load(null,e,t,n)},_autoPurge:function(e){e&&this._purgeNodes.length>=e&&this._purge(this._purgeNodes)},_getEnv:function(){var t=e.config.doc,n=e.UA;return this._env={async:t&&t.createElement("script").async===!0||n.ie>=10,cssFail:n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0,cssLoad:(!n.gecko&&!n.webkit||n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0)&&!(n.chrome&&n.chrome<=18),preservesScriptOrder:!!(n.gecko||n.opera||n.ie&&n.ie>=10)}},_getTransaction:function(t,r){var i=[],o,u,a,f;n.isArray(t)||(t=[t]),r=e.merge(this.options,r),r.attributes=e.merge(this.options.attributes,r.attributes);for(o=0,u=t.length;o<u;++o){f=t[o],a={attributes:{}};if(typeof f=="string")a.url=f;else{if(!f.url)continue;e.mix(a,f,!1,null,0,!0),f=f.url}e.mix(a,r,!1,null,0,!0),a.type||(this.REGEX_CSS.test(f)?a.type="css":(!this.REGEX_JS.test(f),a.type="js")),e.mix(a,a.type==="js"?this.jsOptions:this.cssOptions,!1,null,0,!0),a.attributes.id||(a.attributes.id=e.guid()),a.win?a.doc=a.win.document:a.win=a.doc.defaultView||a.doc.parentWindow,a.charset&&(a.attributes.charset=a.charset),i.push(a)}return new s(i,r)},_load:function(e,t,n,r){var s;return typeof n=="function"&&(r=n,n={}),n||(n={}),n.type=e,n._onFinish=i._onTransactionFinish,this._env||this._getEnv(),s=this._getTransaction(t,n),this._queue.push({callback:r,transaction:s}),this._next(),s},_onTransactionFinish:function(){i._pending=null,i._next()},_next:function(){var e;if(this._pending)return;e=this._queue.shift(),e&&(this._pending=e,e.transaction.execute(e.callback))},_purge:function(t){var n=this._purgeNodes,r=t!==n,i,s;while(s=t.pop()){if(!s._yuiget_finished)continue;s.parentNode&&s.parentNode.removeChild(s),r&&(i=e.Array.indexOf(n,s),i>-1&&n.splice(i,1))}}},i.script=i.js,i.Transaction=s=function(t,n){var r=this;r.id=s._lastId+=1,r.data=n.data,r.errors=[],r.nodes=[],r.options=n,r.requests=t,r._callbacks=[],r._queue=[],r._reqsWaiting=0,r.tId=r.id,r.win=n.win||e.config.win},s._lastId=0,s.prototype={_state:"new",abort:function(e){this._pending=null,this._pendingCSS=null,this._pollTimer=clearTimeout(this._pollTimer),this._queue=[],this._reqsWaiting=0,this.errors.push({error:e||"Aborted"}),this._finish()},execute:function(e){var t=this,n=t.requests,r=t._state,i,s,o,u;if(r==="done"){e&&e(t.errors.length?t.errors:null,t);return}e&&t._callbacks.push(e);if(r==="executing")return;t._state="executing",t._queue=o=[],t.options.timeout&&(t._timeout=setTimeout(function(){t.abort("Timeout")},t.options.timeout)),t._reqsWaiting=n.length;for(i=0,s=n.length;i<s;++i)u=n[i],u.async||u.type==="css"?t._insert(u):o.push(u);t._next()},purge:function(){i._purge(this.nodes)},_createNode:function(e,t,n){var i=n.createElement(e),s,o;r||(o=n.createElement("div"),o.setAttribute("class","a"),r=o.className==="a"?{}:{"for":"htmlFor","class":"className"});for(s in t)t.hasOwnProperty(s)&&i.setAttribute(r[s]||s,t[s]);return i},_finish:function(){var e=this.errors.length?this.errors:null,t=this.options,n=t.context||this,r,i,s;if(this._state==="done")return;this._state="done";for(i=0,s=this._callbacks.length;i<s;++i)this._callbacks[i].call(n,e,this);r=this._getEventData(),e?(t.onTimeout&&e[e.length-1].error==="Timeout"&&t.onTimeout.call(n,r),t.onFailure&&t.onFailure.call(n,r)):t.onSuccess&&t.onSuccess.call(n,r),t.onEnd&&t.onEnd.call(n,r),t._onFinish&&t._onFinish()},_getEventData:function(t){return t?e.merge(this,{abort:this.abort,purge:this.purge,request:t,url:t.url,win:t.win}):this},_getInsertBefore:function(t){var n=t.doc,r=t.insertBefore,s,o,u;return r?typeof r=="string"?n.getElementById(r):r:(s=i._insertCache,u=e.stamp(n),(r=s[u])?r:(r=n.getElementsByTagName("base")[0])?s[u]=r:(r=n.head||n.getElementsByTagName("head")[0],r?(r.appendChild(n.createTextNode("")),s[u]=r.lastChild):s[u]=n.getElementsByTagName("script")[0]))},_insert:function(t){function c(){u._progress("Failed to load "+t.url,t)}function h(){f&&clearTimeout(f),u._progress(null,t)}var n=i._env,r=this._getInsertBefore(t),s=t.type==="js",o=t.node,u=this,a=e.UA,f,l;o||(s?l="script":!n.cssLoad&&a.gecko?l="style":l="link",o=t.node=this._createNode(l,t.attributes,t.doc)),s?(o.setAttribute("src",t.url),t.async?o.async=!0:(n.async&&(o.async=!1),n.preservesScriptOrder||(this._pending=t))):!n.cssLoad&&a.gecko?o.innerHTML=(t.attributes.charset?'@charset "'+t.attributes.charset+'";':"")+'@import "'+t.url+'";':o.setAttribute("href",t.url),s&&a.ie&&(a.ie<9||document.documentMode&&document.documentMode<9)?o.onreadystatechange=function(){/loaded|complete/.test(o.readyState)&&(o.onreadystatechange=null,h())}:!s&&!n.cssLoad?this._poll(t):(a.ie>=10?(o.onerror=function(){setTimeout(c,0)},o.onload=function(){setTimeout(h,0)}):(o.onerror=c,o.onload=h),!n.cssFail&&!s&&(f=setTimeout(c,t.timeout||3e3))),this.nodes.push(o),r.parentNode.insertBefore(o,r)},_next:function(){if(this._pending)return;this._queue.length?this._insert(this._queue.shift()):this._reqsWaiting||this._finish()},_poll:function(t){var n=this,r=n._pendingCSS,i=e.UA.webkit,s,o,u,a,f,l;if(t){r||(r=n._pendingCSS=[]),r.push(t);if(n._pollTimer)return}n._pollTimer=null;for(s=0;s<r.length;++s){f=r[s];if(i){l=f.doc.styleSheets,u=l.length,a=f.node.href;while(--u>=0)if(l[u].href===a){r.splice(s,1),s-=1,n._progress(null,f);break}}else try{o=!!f.node.sheet.cssRules,r.splice(s,1),s-=1,n._progress(null,f)}catch(c){}}r.length&&(n._pollTimer=setTimeout(function(){n._poll.call(n)},n.options.pollInterval))},_progress:function(e,t){var n=this.options;e&&(t.error=e,this.errors.push({error:e,request:t})),t.node._yuiget_finished=t.finished=!0,n.onProgress&&n.onProgress.call(n.context||this,this._getEventData(t)),t.autopurge&&(i._autoPurge(this.options.purgethreshold),i._purgeNodes.push(t.node)),this._pending===t&&(this._pending=null),this._reqsWaiting-=1,this._next()}}},"3.7.3",{requires:["yui-base"]}),YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]}),YUI.add("intl-base",function(e,t){var n=/[, ]/;e.mix(e.namespace("Intl"),{lookupBestLang:function(t,r){function a(e){var t;for(t=0;t<r.length;t+=1)if(e.toLowerCase()===r[t].toLowerCase())return r[t]}var i,s,o,u;e.Lang.isString(t)&&(t=t.split(n));for(i=0;i<t.length;i+=1){s=t[i];if(!s||s==="*")continue;while(s.length>0){o=a(s);if(o)return o;u=s.lastIndexOf("-");if(!(u>=0))break;s=s.substring(0,u),u>=2&&s.charAt(u-2)==="-"&&(s=s.substring(0,u-2))}}return""}})},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-later",function(e,t){var n=[];e.later=function(t,r,i,s,o){t=t||0,s=e.Lang.isUndefined(s)?n:e.Array(s),r=r||e.config.win||e;var u=!1,a=r&&e.Lang.isString(i)?r[i]:i,f=function(){u||(a.apply?a.apply(r,s||n):a(s[0],s[1],s[2],s[3]))},l=o?setInterval(f,t):setTimeout(f,t);return{id:l,interval:o,cancel:function(){u=!0,this.interval?clearInterval(l):clearTimeout(l)}}},e.Lang.later=e.later},"3.7.3",{requires:["yui-base"]}),YUI.add("yui",function(e,t){},"3.7.3",{use:["get","features","intl-base","yui-log","yui-later"]});
diff --git a/js/yui3/yui-core/yui-core-min.js b/js/yui3/yui-core/yui-core-min.js
new file mode 100644
index 000000000..fbd430f16
--- /dev/null
+++ b/js/yui3/yui-core/yui-core-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+typeof YUI!="undefined"&&(YUI._YUI=YUI);var YUI=function(){var e=0,t=this,n=arguments,r=n.length,i=function(e,t){return e&&e.hasOwnProperty&&e instanceof t},s=typeof YUI_config!="undefined"&&YUI_config;i(t,YUI)?(t._init(),YUI.GlobalConfig&&t.applyConfig(YUI.GlobalConfig),s&&t.applyConfig(s),r||t._setup()):t=new YUI;if(r){for(;e<r;e++)t.applyConfig(n[e]);t._setup()}return t.instanceOf=i,t};(function(){var e,t,n="3.7.3",r=".",i="http://yui.yahooapis.com/",s="yui3-js-enabled",o="yui3-css-stamp",u=function(){},a=Array.prototype.slice,f={"io.xdrReady":1,"io.xdrResponse":1,"SWF.eventHandler":1},l=typeof window!="undefined",c=l?window:null,h=l?c.document:null,p=h&&h.documentElement,d=p&&p.className,v={},m=(new Date).getTime(),g=function(e,t,n,r){e&&e.addEventListener?e.addEventListener(t,n,r):e&&e.attachEvent&&e.attachEvent("on"+t,n)},y=function(e,t,n,r){if(e&&e.removeEventListener)try{e.removeEventListener(t,n,r)}catch(i){}else e&&e.detachEvent&&e.detachEvent("on"+t,n)},b=function(){YUI.Env.windowLoaded=!0,YUI.Env.DOMReady=!0,l&&y(window,"load",b)},w=function(e,t){var n=e.Env._loader,r=["loader-base"],i=YUI.Env,s=i.mods;return n?(n.ignoreRegistered=!1,n.onEnd=null,n.data=null,n.required=[],n.loadType=null):(n=new e.Loader(e.config),e.Env._loader=n),s&&s.loader&&(r=[].concat(r,YUI.Env.loaderExtras)),YUI.Env.core=e.Array.dedupe([].concat(YUI.Env.core,r)),n},E=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},S={success:!0};p&&d.indexOf(s)==-1&&(d&&(d+=" "),d+=s,p.className=d),n.indexOf("@")>-1&&(n="3.5.0"),e={applyConfig:function(e){e=e||u;var t,n,r=this.config,i=r.modules,s=r.groups,o=r.aliases,a=this.Env._loader;for(n in e)e.hasOwnProperty(n)&&(t=e[n],i&&n=="modules"?E(i,t):o&&n=="aliases"?E(o,t):s&&n=="groups"?E(s,t):n=="win"?(r[n]=t&&t.contentWindow||t,r.doc=r[n]?r[n].document:null):n!="_yuid"&&(r[n]=t));a&&a._config(e)},_config:function(e){this.applyConfig(e)},_init:function(){var e,t,r=this,s=YUI.Env,u=r.Env,a;r.version=n;if(!u){r.Env={core:["intl-base"],loaderExtras:["loader-rollup","loader-yui3"],mods:{},versions:{},base:i,cdn:i+n+"/build/",_idx:0,_used:{},_attached:{},_missed:[],_yidx:0,_uidx:0,_guidp:"y",_loaded:{},_BASE_RE:/(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,parseBasePath:function(e,t){var n=e.match(t),r,i;return n&&(r=RegExp.leftContext||e.slice(0,e.indexOf(n[0])),i=n[3],n[1]&&(r+="?"+n[1]),r={filter:i,path:r}),r},getBase:s&&s.getBase||function(t){var n=h&&h.getElementsByTagName("script")||[],i=u.cdn,s,o,a,f;for(o=0,a=n.length;o<a;++o){f=n[o].src;if(f){s=r.Env.parseBasePath(f,t);if(s){e=s.filter,i=s.path;break}}}return i}},u=r.Env,u._loaded[n]={};if(s&&r!==YUI)u._yidx=++s._yidx,u._guidp=("yui_"+n+"_"+u._yidx+"_"+m).replace(/\./g,"_").replace(/-/g,"_");else if(YUI._YUI){s=YUI._YUI.Env,u._yidx+=s._yidx,u._uidx+=s._uidx;for(a in s)a in u||(u[a]=s[a]);delete YUI._YUI}r.id=r.stamp(r),v[r.id]=r}r.constructor=YUI,r.config=r.config||{bootstrap:!0,cacheUse:!0,debug:!0,doc:h,fetchCSS:!0,throwFail:!0,useBrowserConsole:!0,useNativeES5:!0,win:c},h&&!h.getElementById(o)&&(t=h.createElement("div"),t.innerHTML='<div id="'+o+'" style="position: absolute !important; visibility: hidden !important"></div>',YUI.Env.cssStampEl=t.firstChild,h.body?h.body.appendChild(YUI.Env.cssStampEl):p.insertBefore(YUI.Env.cssStampEl,p.firstChild)),r.config.lang=r.config.lang||"en-US",r.config.base=YUI.config.base||r.Env.getBase(r.Env._BASE_RE);if(!e||!"mindebug".indexOf(e))e="min";e=e?"-"+e:e,r.config.loaderPath=YUI.config.loaderPath||"loader/loader"+e+".js"},_setup:function(e){var t,n=this,r=[],i=YUI.Env.mods,s=n.config.core||[].concat(YUI.Env.core);for(t=0;t<s.length;t++)i[s[t]]&&r.push(s[t]);n._attach(["yui-base"]),n._attach(r),n.Loader&&w(n)},applyTo:function(e,t,n){if(t in f){var r=v[e],i,s,o;if(r){i=t.split("."),s=r;for(o=0;o<i.length;o+=1)s=s[i[o]],s||this.log("applyTo not found: "+t,"warn","yui");return s&&s.apply(r,n)}return null}return this.log(t+": applyTo not allowed","warn","yui"),null},add:function(e,t,n,r){r=r||{};var i=YUI.Env,s={name:e,fn:t,version:n,details:r},o={},u,a,f,l=i.versions;i.mods[e]=s,l[n]=l[n]||{},l[n][e]=s;for(f in v)v.hasOwnProperty(f)&&(a=v[f],o[a.id]||(o[a.id]=!0,u=a.Env._loader,u&&(!u.moduleInfo[e]||u.moduleInfo[e].temp)&&u.addModule(r,e)));return this},_attach:function(e,t){var n,r,i,s,o,u,a,f=YUI.Env.mods,l=YUI.Env.aliases,c=this,h,p=YUI.Env._renderedMods,d=c.Env._loader,v=c.Env._attached,m=e.length,d,g,y,b=[];for(n=0;n<m;n++){r=e[n],i=f[r],b.push(r);if(d&&d.conditions[r])for(h in d.conditions[r])d.conditions[r].hasOwnProperty(h)&&(g=d.conditions[r][h],y=g&&(g.ua&&c.UA[g.ua]||g.test&&g.test(c)),y&&b.push(g.name))}e=b,m=e.length;for(n=0;n<m;n++)if(!v[e[n]]){r=e[n],i=f[r];if(l&&l[r]&&!i){c._attach(l[r]);continue}if(!i)d&&d.moduleInfo[r]&&(i=d.moduleInfo[r],t=!0),!t&&r&&r.indexOf("skin-")===-1&&r.indexOf("css")===-1&&(c.Env._missed.push(r),c.Env._missed=c.Array.dedupe(c.Env._missed),c.message("NOT loaded: "+r,"warn","yui"));else{v[r]=!0;for(h=0;h<c.Env._missed.length;h++)c.Env._missed[h]===r&&(c.message("Found: "+r+" (was reported as missing earlier)","warn","yui"),c.Env._missed.splice(h,1));if(d&&p&&p[r]&&p[r].temp){d.getRequires(p[r]),o=[];for(h in d.moduleInfo[r].expanded_map)d.moduleInfo[r].expanded_map.hasOwnProperty(h)&&o.push(h);c._attach(o)}s=i.details,o=s.requires,u=s.use,a=s.after,s.lang&&(o=o||[],o.unshift("intl"));if(o)for(h=0;h<o.length;h++)if(!v[o[h]]){if(!c._attach(o))return!1;break}if(a)for(h=0;h<a.length;h++)if(!v[a[h]]){if(!c._attach(a,!0))return!1;break}if(i.fn)if(c.config.throwFail)i.fn(c,r);else try{i.fn(c,r)}catch(w){return c.error("Attach error: "+r,w,r),!1}if(u)for(h=0;h<u.length;h++)if(!v[u[h]]){if(!c._attach(u))return!1;break}}}return!0},_delayCallback:function(e,t){var n=this,r=["event-base"];return t=n.Lang.isObject(t)?t:{event:t},t.event==="load"&&r.push("event-synthetic"),function(){var i=arguments;n._use(r,function(){n.on(t.event,function(){i[1].delayUntil=t.event,e.apply(n,i)},t.args)})}},use:function(){var e=a.call(arguments,0),t=e[e.length-1],n=this,r=0,i=[],s,o=n.Env,u=!0;n.Lang.isFunction(t)?(e.pop(),n.config.delayUntil&&(t=n._delayCallback(t,n.config.delayUntil))):t=null,n.Lang.isArray(e[0])&&(e=e[0]);if(n.config.cacheUse){while(s=e[r++])if(!o._attached[s]){u=!1;break}if(u)return e.length,n._notify(t,S,e),n}return n._loading?(n._useQueue=n._useQueue||new n.Queue,n._useQueue.add([e,t])):n._use(e,function(n,r){n._notify(t,r,e)}),n},_notify:function(e,t,n){if(!t.success&&this.config.loadErrorFn)this.config.loadErrorFn.call(this,this,e,t,n);else if(e){this.Env._missed&&this.Env._missed.length&&(t.msg="Missing modules: "+this.Env._missed.join(),t.success=!1);if(this.config.throwFail)e(this,t);else try{e(this,t)}catch(r){this.error("use callback error",r,n)}}},_use:function(e,t){this.Array||this._attach(["yui-base"]);var r,i,s,o,u=this,a=YUI.Env,f=a.mods,l=u.Env,c=l._used,h=a.aliases,p=a._loaderQueue,d=e[0],v=u.Array,m=u.config,g=m.bootstrap,y=[],b,E=[],S=!0,x=m.fetchCSS,T=function(e,t){var r=0,i=[],s,o,u,l,p;if(!e.length)return;if(h){o=e.length;for(r=0;r<o;r++)h[e[r]]&&!f[e[r]]?i=[].concat(i,h[e[r]]):i.push(e[r]);e=i}o=e.length;for(r=0;r<o;r++){s=e[r],t||E.push(s);if(c[s])continue;u=f[s],l=null,p=null,u?(c[s]=!0,l=u.details.requires,p=u.details.use):a._loaded[n][s]?c[s]=!0:y.push(s),l&&l.length&&T(l),p&&p.length&&T(p,1)}},N=function(n){var r=n||{success:!0,msg:"not dynamic"},i,s,o=!0,a=r.data;u._loading=!1,a&&(s=y,y=[],E=[],T(a),i=y.length,i&&[].concat(y).sort().join()==s.sort().join()&&(i=!1)),i&&a?(u._loading=!0,u._use(y,function(){u._attach(a)&&u._notify(t,r,a)})):(a&&(o=u._attach(a)),o&&u._notify(t,r,e)),u._useQueue&&u._useQueue.size()&&!u._loading&&u._use.apply(u,u._useQueue.next())};if(d==="*"){e=[];for(b in f)f.hasOwnProperty(b)&&e.push(b);return S=u._attach(e),S&&N(),u}return(f.loader||f["loader-base"])&&!u.Loader&&u._attach(["loader"+(f.loader?"":"-base")]),g&&u.Loader&&e.length&&(i=w(u),i.require(e),i.ignoreRegistered=!0,i._boot=!0,i.calculate(null,x?null:"js"),e=i.sorted,i._boot=!1),T(e),r=y.length,r&&(y=v.dedupe(y),r=y.length),g&&r&&u.Loader?(u._loading=!0,i=w(u),i.onEnd=N,i.context=u,i.data=e,i.ignoreRegistered=!1,i.require(e),i.insert(null,x?null:"js")):g&&r&&u.Get&&!l.bootstrapped?(u._loading=!0,s=function(){u._loading=!1,p.running=!1,l.bootstrapped=!0,a._bootstrapping=!1,u._attach(["loader"])&&u._use(e,t)},a._bootstrapping?p.add(s):(a._bootstrapping=!0,u.Get.script(m.base+m.loaderPath,{onEnd:s}))):(S=u._attach(e),S&&N()),u},namespace:function(){var e=arguments,t,n=0,i,s,o;for(;n<e.length;n++){t=this,o=e[n];if(o.indexOf(r)>-1){s=o.split(r);for(i=s[0]=="YAHOO"?1:0;i<s.length;i++)t[s[i]]=t[s[i]]||{},t=t[s[i]]}else t[o]=t[o]||{},t=t[o]}return t},log:u,message:u,dump:function(e){return""+e},error:function(e,t,n){var r=this,i;r.config.errorFn&&(i=r.config.errorFn.apply(r,arguments));if(!i)throw t||new Error(e);return r.message(e,"error",""+n),r},guid:function(e){var t=this.Env._guidp+"_"+ ++this.Env._uidx;return e?e+t:t},stamp:function(e,t){var n;if(!e)return e;e.uniqueID&&e.nodeType&&e.nodeType!==9?n=e.uniqueID:n=typeof e=="string"?e:e._yuid;if(!n){n=this.guid();if(!t)try{e._yuid=n}catch(r){n=null}}return n},destroy:function(){var e=this;e.Event&&e.Event._unload(),delete v[e.id],delete e.Env,delete e.config}},YUI.prototype=e;for(t in e)e.hasOwnProperty(t)&&(YUI[t]=e[t]);YUI.applyConfig=function(e){if(!e)return;YUI.GlobalConfig&&this.prototype.applyConfig.call(this,YUI.GlobalConfig),this.prototype.applyConfig.call(this,e),YUI.GlobalConfig=this.config},YUI._init(),l?g(window,"load",b):b(),YUI.Env.add=g,YUI.Env.remove=y,typeof exports=="object"&&(exports.YUI=YUI)})(),YUI.add("yui-base",function(e,t){function h(e,t,n){var r,i;t||(t=0);if(n||h.test(e))try{return l.slice.call(e,t)}catch(s){i=[];for(r=e.length;t<r;++t)i.push(e[t]);return i}return[e]}function p(){this._init(),this.add.apply(this,arguments)}var n=e.Lang||(e.Lang={}),r=String.prototype,i=Object.prototype.toString,s={"undefined":"undefined",number:"number","boolean":"boolean",string:"string","[object Function]":"function","[object RegExp]":"regexp","[object Array]":"array","[object Date]":"date","[object Error]":"error"},o=/\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,u=/^\s+|\s+$/g,a=/\{\s*\[(?:native code|function)\]\s*\}/i;n._isNative=function(t){return!!(e.config.useNativeES5&&t&&a.test(t))},n.isArray=n._isNative(Array.isArray)?Array.isArray:function(e){return n.type(e)==="array"},n.isBoolean=function(e){return typeof e=="boolean"},n.isDate=function(e){return n.type(e)==="date"&&e.toString()!=="Invalid Date"&&!isNaN(e)},n.isFunction=function(e){return n.type(e)==="function"},n.isNull=function(e){return e===null},n.isNumber=function(e){return typeof e=="number"&&isFinite(e)},n.isObject=function(e,t){var r=typeof e;return e&&(r==="object"||!t&&(r==="function"||n.isFunction(e)))||!1},n.isString=function(e){return typeof e=="string"},n.isUndefined=function(e){return typeof e=="undefined"},n.isValue=function(e){var t=n.type(e);switch(t){case"number":return isFinite(e);case"null":case"undefined":return!1;default:return!!t}},n.now=Date.now||function(){return(new Date).getTime()},n.sub=function(e,t){return e.replace?e.replace(o,function(e,r){return n.isUndefined(t[r])?e:t[r]}):e},n.trim=r.trim?function(e){return e&&e.trim?e.trim():e}:function(e){try{return e.replace(u,"")}catch(t){return e}},n.trimLeft=r.trimLeft?function(e){return e.trimLeft()}:function(e){return e.replace(/^\s+/,"")},n.trimRight=r.trimRight?function(e){return e.trimRight()}:function(e){return e.replace(/\s+$/,"")},n.type=function(e){return s[typeof e]||s[i.call(e)]||(e?"object":"null")};var f=e.Lang,l=Array.prototype,c=Object.prototype.hasOwnProperty;e.Array=h,h.dedupe=function(e){var t={},n=[],r,i,s;for(r=0,s=e.length;r<s;++r)i=e[r],c.call(t,i)||(t[i]=1,n.push(i));return n},h.each=h.forEach=f._isNative(l.forEach)?function(t,n,r){return l.forEach.call(t||[],n,r||e),e}:function(t,n,r){for(var i=0,s=t&&t.length||0;i<s;++i)i in t&&n.call(r||e,t[i],i,t);return e},h.hash=function(e,t){var n={},r=t&&t.length||0,i,s;for(i=0,s=e.length;i<s;++i)i in e&&(n[e[i]]=r>i&&i in t?t[i]:!0);return n},h.indexOf=f._isNative(l.indexOf)?function(e,t,n){return l.indexOf.call(e,t,n)}:function(e,t,n){var r=e.length;n=+n||0,n=(n>0||-1)*Math.floor(Math.abs(n)),n<0&&(n+=r,n<0&&(n=0));for(;n<r;++n)if(n in e&&e[n]===t)return n;return-1},h.numericSort=function(e,t){return e-t},h.some=f._isNative(l.some)?function(e,t,n){return l.some.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&t.call(n,e[r],r,e))return!0;return!1},h.test=function(e){var t=0;if(f.isArray(e))t=1;else if(f.isObject(e))try{"length"in e&&!e.tagName&&(!e.scrollTo||!e.document)&&!e.apply&&(t=2)}catch(n){}return t},p.prototype={_init:function(){this._q=[]},next:function(){return this._q.shift()},last:function(){return this._q.pop()},add:function(){return this._q.push.apply(this._q,arguments),this},size:function(){return this._q.length}},e.Queue=p,YUI.Env._loaderQueue=YUI.Env._loaderQueue||new p;var d="__",c=Object.prototype.hasOwnProperty,v=e.Lang.isObject;e.cached=function(e,t,n){return t||(t={}),function(r){var i=arguments.length>1?Array.prototype.join.call(arguments,d):String(r);if(!(i in t)||n&&t[i]==n)t[i]=e.apply(e,arguments);return t[i]}},e.getLocation=function(){var t=e.config.win;return t&&t.location},e.merge=function(){var e=0,t=arguments.length,n={},r,i;for(;e<t;++e){i=arguments[e];for(r in i)c.call(i,r)&&(n[r]=i[r])}return n},e.mix=function(t,n,r,i,s,o){var u,a,f,l,h,p,d;if(!t||!n)return t||e;if(s){s===2&&e.mix(t.prototype,n.prototype,r,i,0,o),f=s===1||s===3?n.prototype:n,d=s===1||s===4?t.prototype:t;if(!f||!d)return t}else f=n,d=t;u=r&&!o;if(i)for(l=0,p=i.length;l<p;++l){h=i[l];if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}else{for(h in f){if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}e.Object._hasEnumBug&&e.mix(d,f,r,e.Object._forceEnum,s,o)}return t};var f=e.Lang,c=Object.prototype.hasOwnProperty,m,g=e.Object=f._isNative(Object.create)?function(e){return Object.create(e)}:function(){function e(){}return function(t){return e.prototype=t,new e}}(),y=g._forceEnum=["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf"],b=g._hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),w=g._hasProtoEnumBug=function(){}.propertyIsEnumerable("prototype"),E=g.owns=function(e,t){return!!e&&c.call(e,t)};g.hasKey=E,g.keys=f._isNative(Object.keys)?Object.keys:function(e){if(!f.isObject(e))throw new TypeError("Object.keys called on a non-object");var t=[],n,r,i;if(w&&typeof e=="function")for(r in e)E(e,r)&&r!=="prototype"&&t.push(r);else for(r in e)E(e,r)&&t.push(r);if(b)for(n=0,i=y.length;n<i;++n)r=y[n],E(e,r)&&t.push(r);return t},g.values=function(e){var t=g.keys(e),n=0,r=t.length,i=[];for(;n<r;++n)i.push(e[t[n]]);return i},g.size=function(e){try{return g.keys(e).length}catch(t){return 0}},g.hasValue=function(t,n){return e.Array.indexOf(g.values(t),n)>-1},g.each=function(t,n,r,i){var s;for(s in t)(i||E(t,s))&&n.call(r||e,t[s],s,t);return e},g.some=function(t,n,r,i){var s;for(s in t)if(i||E(t,s))if(n.call(r||e,t[s],s,t))return!0;return!1},g.getValue=function(t,n){if(!f.isObject(t))return m;var r,i=e.Array(n),s=i.length;for(r=0;t!==m&&r<s;r++)t=t[i[r]];return t},g.setValue=function(t,n,r){var i,s=e.Array(n),o=s.length-1,u=t;if(o>=0){for(i=0;u!==m&&i<o;i++)u=u[s[i]];if(u===m)return m;u[s[i]]=r}return t},g.isEmpty=function(e){return!g.keys(Object(e)).length},YUI.Env.parseUA=function(t){var n=function(e){var t=0;return parseFloat(e.replace(/\./g,function(){return t++===1?"":"."}))},r=e.config.win,i=r&&r.navigator,s={ie:0,opera:0,gecko:0,webkit:0,safari:0,chrome:0,mobile:null,air:0,phantomjs:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,silk:0,accel:!1,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null,nodejs:0,winjs:typeof Windows!="undefined"&&!!Windows.System,touchEnabled:!1},o=t||i&&i.userAgent,u=r&&r.location,a=u&&u.href,f;return s.userAgent=o,s.secure=a&&a.toLowerCase().indexOf("https")===0,o&&(/windows|win32/i.test(o)?s.os="windows":/macintosh|mac_powerpc/i.test(o)?s.os="macintosh":/android/i.test(o)?s.os="android":/symbos/i.test(o)?s.os="symbos":/linux/i.test(o)?s.os="linux":/rhino/i.test(o)&&(s.os="rhino"),/KHTML/.test(o)&&(s.webkit=1),/IEMobile|XBLWP7/.test(o)&&(s.mobile="windows"),/Fennec/.test(o)&&(s.mobile="gecko"),f=o.match(/AppleWebKit\/([^\s]*)/),f&&f[1]&&(s.webkit=n(f[1]),s.safari=s.webkit,/PhantomJS/.test(o)&&(f=o.match(/PhantomJS\/([^\s]*)/),f&&f[1]&&(s.phantomjs=n(f[1]))),/ Mobile\//.test(o)||/iPad|iPod|iPhone/.test(o)?(s.mobile="Apple",f=o.match(/OS ([^\s]*)/),f&&f[1]&&(f=n(f[1].replace("_","."))),s.ios=f,s.os="ios",s.ipad=s.ipod=s.iphone=0,f=o.match(/iPad|iPod|iPhone/),f&&f[0]&&(s[f[0].toLowerCase()]=s.ios)):(f=o.match(/NokiaN[^\/]*|webOS\/\d\.\d/),f&&(s.mobile=f[0]),/webOS/.test(o)&&(s.mobile="WebOS",f=o.match(/webOS\/([^\s]*);/),f&&f[1]&&(s.webos=n(f[1]))),/ Android/.test(o)&&(/Mobile/.test(o)&&(s.mobile="Android"),f=o.match(/Android ([^\s]*);/),f&&f[1]&&(s.android=n(f[1]))),/Silk/.test(o)&&(f=o.match(/Silk\/([^\s]*)\)/),f&&f[1]&&(s.silk=n(f[1])),s.android||(s.android=2.34,s.os="Android"),/Accelerated=true/.test(o)&&(s.accel=!0))),f=o.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/),f&&f[1]&&f[2]?(s.chrome=n(f[2]),s.safari=0,f[1]==="CrMo"&&(s.mobile="chrome")):(f=o.match(/AdobeAIR\/([^\s]*)/),f&&(s.air=f[0]))),s.webkit||(/Opera/.test(o)?(f=o.match(/Opera[\s\/]([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),f=o.match(/Version\/([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),/Opera Mobi/.test(o)&&(s.mobile="opera",f=o.replace("Opera Mobi","").match(/Opera ([^\s]*)/),f&&f[1]&&(s.opera=n(f[1]))),f=o.match(/Opera Mini[^;]*/),f&&(s.mobile=f[0])):(f=o.match(/MSIE\s([^;]*)/),f&&f[1]?s.ie=n(f[1]):(f=o.match(/Gecko\/([^\s]*)/),f&&(s.gecko=1,f=o.match(/rv:([^\s\)]*)/),f&&f[1]&&(s.gecko=n(f[1]))))))),r&&i&&!(s.chrome&&s.chrome<6)&&(s.touchEnabled="ontouchstart"in r||"msMaxTouchPoints"in i&&i.msMaxTouchPoints>0),t||(typeof process=="object"&&process.versions&&process.versions.node&&(s.os=process.platform,s.nodejs=n(process.versions.node)),YUI.Env.UA=s),s},e.UA=YUI.Env.UA||YUI.Env.parseUA(),e.UA.compareVersions=function(e,t){var n,r,i,s,o,u;if(e===t)return 0;r=(e+"").split("."),s=(t+"").split(".");for(o=0,u=Math.max(r.length,s.length);o<u;++o){n=parseInt(r[o],10),i=parseInt(s[o],10),isNaN(n)&&(n=0),isNaN(i)&&(i=0);if(n<i)return-1;if(n>i)return 1}return 0},YUI.Env.aliases={anim:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],"anim-shape-transform":["anim-shape"],app:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],attribute:["attribute-base","attribute-complex"],autocomplete:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],base:["base-base","base-pluginhost","base-build"],cache:["cache-base","cache-offline","cache-plugin"],collection:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],controller:["router"],dataschema:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],datasource:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],datatable:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],"datatable-deprecated":["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],datatype:["datatype-date","datatype-number","datatype-xml"],"datatype-date":["datatype-date-parse","datatype-date-format","datatype-date-math"],"datatype-number":["datatype-number-parse","datatype-number-format"],"datatype-xml":["datatype-xml-parse","datatype-xml-format"],dd:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],dom:["dom-base","dom-screen","dom-style","selector-native","selector"],editor:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],event:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],"event-custom":["event-custom-base","event-custom-complex"],"event-gestures":["event-flick","event-move"],handlebars:["handlebars-compiler"],highlight:["highlight-base","highlight-accentfold"],history:["history-base","history-hash","history-hash-ie","history-html5"],io:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],json:["json-parse","json-stringify"],loader:["loader-base","loader-rollup","loader-yui3"],node:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],pluginhost:["pluginhost-base","pluginhost-config"],querystring:["querystring-parse","querystring-stringify"],recordset:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],resize:["resize-base","resize-proxy","resize-constrain"],slider:["slider-base","slider-value-range","clickable-rail","range-slider"],text:["text-accentfold","text-wordbreak"],widget:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]}},"3.7.3");
diff --git a/js/yui3/yui-later/yui-later-min.js b/js/yui3/yui-later/yui-later-min.js
new file mode 100644
index 000000000..d19073eaa
--- /dev/null
+++ b/js/yui3/yui-later/yui-later-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yui-later",function(e,t){var n=[];e.later=function(t,r,i,s,o){t=t||0,s=e.Lang.isUndefined(s)?n:e.Array(s),r=r||e.config.win||e;var u=!1,a=r&&e.Lang.isString(i)?r[i]:i,f=function(){u||(a.apply?a.apply(r,s||n):a(s[0],s[1],s[2],s[3]))},l=o?setInterval(f,t):setTimeout(f,t);return{id:l,interval:o,cancel:function(){u=!0,this.interval?clearInterval(l):clearTimeout(l)}}},e.Lang.later=e.later},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/yui-log-nodejs/yui-log-nodejs-min.js b/js/yui3/yui-log-nodejs/yui-log-nodejs-min.js
new file mode 100644
index 000000000..aa0c7df79
--- /dev/null
+++ b/js/yui3/yui-log-nodejs/yui-log-nodejs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yui-log-nodejs",function(e,t){var n=require(process.binding("natives").util?"util":"sys"),r=!1;try{var i=require("stdio");r=i.isStderrATTY()}catch(s){r=!0}e.config.useColor=r,e.consoleColor=function(e,t){return this.config.useColor?(t||(t="32"),"["+t+"m"+e+""):e};var o=function(e,t,r){var i="";this.id&&(i="["+this.id+"]:"),t=t||"info",r=r?this.consoleColor(" ("+r.toLowerCase()+"):",35):"",e===null&&(e="null");if(typeof e=="object"||e instanceof Array)try{e.tagName||e._yuid||e._query?e=e.toString():e=n.inspect(e)}catch(s){}var o="37;40",u=e?"":31;t+="";switch(t.toLowerCase()){case"error":o=u=31;break;case"warn":o=33;break;case"debug":o=34}typeof e=="string"&&e&&e.indexOf("\n")!==-1&&(e="\n"+e),n.error(this.consoleColor(t.toLowerCase()+":",o)+r+" "+this.consoleColor(e,u))};e.config.logFn||(e.config.logFn=o)},"3.7.3");
diff --git a/js/yui3/yui-log/yui-log-min.js b/js/yui3/yui-log/yui-log-min.js
new file mode 100644
index 000000000..110827eb5
--- /dev/null
+++ b/js/yui3/yui-log/yui-log-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/yui-nodejs/yui-nodejs-min.js b/js/yui3/yui-nodejs/yui-nodejs-min.js
new file mode 100644
index 000000000..d623cac69
--- /dev/null
+++ b/js/yui3/yui-nodejs/yui-nodejs-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+typeof YUI!="undefined"&&(YUI._YUI=YUI);var YUI=function(){var e=0,t=this,n=arguments,r=n.length,i=function(e,t){return e&&e.hasOwnProperty&&e instanceof t},s=typeof YUI_config!="undefined"&&YUI_config;i(t,YUI)?(t._init(),YUI.GlobalConfig&&t.applyConfig(YUI.GlobalConfig),s&&t.applyConfig(s),r||t._setup()):t=new YUI;if(r){for(;e<r;e++)t.applyConfig(n[e]);t._setup()}return t.instanceOf=i,t};(function(){var e,t,n="3.7.3",r=".",i="http://yui.yahooapis.com/",s="yui3-js-enabled",o="yui3-css-stamp",u=function(){},a=Array.prototype.slice,f={"io.xdrReady":1,"io.xdrResponse":1,"SWF.eventHandler":1},l=typeof window!="undefined",c=l?window:null,h=l?c.document:null,p=h&&h.documentElement,d=p&&p.className,v={},m=(new Date).getTime(),g=function(e,t,n,r){e&&e.addEventListener?e.addEventListener(t,n,r):e&&e.attachEvent&&e.attachEvent("on"+t,n)},y=function(e,t,n,r){if(e&&e.removeEventListener)try{e.removeEventListener(t,n,r)}catch(i){}else e&&e.detachEvent&&e.detachEvent("on"+t,n)},b=function(){YUI.Env.windowLoaded=!0,YUI.Env.DOMReady=!0,l&&y(window,"load",b)},w=function(e,t){var n=e.Env._loader,r=["loader-base"],i=YUI.Env,s=i.mods;return n?(n.ignoreRegistered=!1,n.onEnd=null,n.data=null,n.required=[],n.loadType=null):(n=new e.Loader(e.config),e.Env._loader=n),s&&s.loader&&(r=[].concat(r,YUI.Env.loaderExtras)),YUI.Env.core=e.Array.dedupe([].concat(YUI.Env.core,r)),n},E=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},S={success:!0};p&&d.indexOf(s)==-1&&(d&&(d+=" "),d+=s,p.className=d),n.indexOf("@")>-1&&(n="3.5.0"),e={applyConfig:function(e){e=e||u;var t,n,r=this.config,i=r.modules,s=r.groups,o=r.aliases,a=this.Env._loader;for(n in e)e.hasOwnProperty(n)&&(t=e[n],i&&n=="modules"?E(i,t):o&&n=="aliases"?E(o,t):s&&n=="groups"?E(s,t):n=="win"?(r[n]=t&&t.contentWindow||t,r.doc=r[n]?r[n].document:null):n!="_yuid"&&(r[n]=t));a&&a._config(e)},_config:function(e){this.applyConfig(e)},_init:function(){var e,t,r=this,s=YUI.Env,u=r.Env,a;r.version=n;if(!u){r.Env={core:["get","features","intl-base","yui-log","yui-log-nodejs","yui-later","loader-base","loader-rollup","loader-yui3"],loaderExtras:["loader-rollup","loader-yui3"],mods:{},versions:{},base:i,cdn:i+n+"/build/",_idx:0,_used:{},_attached:{},_missed:[],_yidx:0,_uidx:0,_guidp:"y",_loaded:{},_BASE_RE:/(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,parseBasePath:function(e,t){var n=e.match(t),r,i;return n&&(r=RegExp.leftContext||e.slice(0,e.indexOf(n[0])),i=n[3],n[1]&&(r+="?"+n[1]),r={filter:i,path:r}),r},getBase:s&&s.getBase||function(t){var n=h&&h.getElementsByTagName("script")||[],i=u.cdn,s,o,a,f;for(o=0,a=n.length;o<a;++o){f=n[o].src;if(f){s=r.Env.parseBasePath(f,t);if(s){e=s.filter,i=s.path;break}}}return i}},u=r.Env,u._loaded[n]={};if(s&&r!==YUI)u._yidx=++s._yidx,u._guidp=("yui_"+n+"_"+u._yidx+"_"+m).replace(/\./g,"_").replace(/-/g,"_");else if(YUI._YUI){s=YUI._YUI.Env,u._yidx+=s._yidx,u._uidx+=s._uidx;for(a in s)a in u||(u[a]=s[a]);delete YUI._YUI}r.id=r.stamp(r),v[r.id]=r}r.constructor=YUI,r.config=r.config||{bootstrap:!0,cacheUse:!0,debug:!0,doc:h,fetchCSS:!0,throwFail:!0,useBrowserConsole:!0,useNativeES5:!0,win:c},h&&!h.getElementById(o)&&(t=h.createElement("div"),t.innerHTML='<div id="'+o+'" style="position: absolute !important; visibility: hidden !important"></div>',YUI.Env.cssStampEl=t.firstChild,h.body?h.body.appendChild(YUI.Env.cssStampEl):p.insertBefore(YUI.Env.cssStampEl,p.firstChild)),r.config.lang=r.config.lang||"en-US",r.config.base=YUI.config.base||r.Env.getBase(r.Env._BASE_RE);if(!e||!"mindebug".indexOf(e))e="min";e=e?"-"+e:e,r.config.loaderPath=YUI.config.loaderPath||"loader/loader"+e+".js"},_setup:function(e){var t,n=this,r=[],i=YUI.Env.mods,s=n.config.core||[].concat(YUI.Env.core);for(t=0;t<s.length;t++)i[s[t]]&&r.push(s[t]);n._attach(["yui-base"]),n._attach(r),n.Loader&&w(n)},applyTo:function(e,t,n){if(t in f){var r=v[e],i,s,o;if(r){i=t.split("."),s=r;for(o=0;o<i.length;o+=1)s=s[i[o]],s||this.log("applyTo not found: "+t,"warn","yui");return s&&s.apply(r,n)}return null}return this.log(t+": applyTo not allowed","warn","yui"),null},add:function(e,t,n,r){r=r||{};var i=YUI.Env,s={name:e,fn:t,version:n,details:r},o={},u,a,f,l=i.versions;i.mods[e]=s,l[n]=l[n]||{},l[n][e]=s;for(f in v)v.hasOwnProperty(f)&&(a=v[f],o[a.id]||(o[a.id]=!0,u=a.Env._loader,u&&(!u.moduleInfo[e]||u.moduleInfo[e].temp)&&u.addModule(r,e)));return this},_attach:function(e,t){var n,r,i,s,o,u,a,f=YUI.Env.mods,l=YUI.Env.aliases,c=this,h,p=YUI.Env._renderedMods,d=c.Env._loader,v=c.Env._attached,m=e.length,d,g,y,b=[];for(n=0;n<m;n++){r=e[n],i=f[r],b.push(r);if(d&&d.conditions[r])for(h in d.conditions[r])d.conditions[r].hasOwnProperty(h)&&(g=d.conditions[r][h],y=g&&(g.ua&&c.UA[g.ua]||g.test&&g.test(c)),y&&b.push(g.name))}e=b,m=e.length;for(n=0;n<m;n++)if(!v[e[n]]){r=e[n],i=f[r];if(l&&l[r]&&!i){c._attach(l[r]);continue}if(!i)d&&d.moduleInfo[r]&&(i=d.moduleInfo[r],t=!0),!t&&r&&r.indexOf("skin-")===-1&&r.indexOf("css")===-1&&(c.Env._missed.push(r),c.Env._missed=c.Array.dedupe(c.Env._missed),c.message("NOT loaded: "+r,"warn","yui"));else{v[r]=!0;for(h=0;h<c.Env._missed.length;h++)c.Env._missed[h]===r&&(c.message("Found: "+r+" (was reported as missing earlier)","warn","yui"),c.Env._missed.splice(h,1));if(d&&p&&p[r]&&p[r].temp){d.getRequires(p[r]),o=[];for(h in d.moduleInfo[r].expanded_map)d.moduleInfo[r].expanded_map.hasOwnProperty(h)&&o.push(h);c._attach(o)}s=i.details,o=s.requires,u=s.use,a=s.after,s.lang&&(o=o||[],o.unshift("intl"));if(o)for(h=0;h<o.length;h++)if(!v[o[h]]){if(!c._attach(o))return!1;break}if(a)for(h=0;h<a.length;h++)if(!v[a[h]]){if(!c._attach(a,!0))return!1;break}if(i.fn)if(c.config.throwFail)i.fn(c,r);else try{i.fn(c,r)}catch(w){return c.error("Attach error: "+r,w,r),!1}if(u)for(h=0;h<u.length;h++)if(!v[u[h]]){if(!c._attach(u))return!1;break}}}return!0},_delayCallback:function(e,t){var n=this,r=["event-base"];return t=n.Lang.isObject(t)?t:{event:t},t.event==="load"&&r.push("event-synthetic"),function(){var i=arguments;n._use(r,function(){n.on(t.event,function(){i[1].delayUntil=t.event,e.apply(n,i)},t.args)})}},use:function(){var e=a.call(arguments,0),t=e[e.length-1],n=this,r=0,i=[],s,o=n.Env,u=!0;n.Lang.isFunction(t)?(e.pop(),n.config.delayUntil&&(t=n._delayCallback(t,n.config.delayUntil))):t=null,n.Lang.isArray(e[0])&&(e=e[0]);if(n.config.cacheUse){while(s=e[r++])if(!o._attached[s]){u=!1;break}if(u)return e.length,n._notify(t,S,e),n}return n._loading?(n._useQueue=n._useQueue||new n.Queue,n._useQueue.add([e,t])):n._use(e,function(n,r){n._notify(t,r,e)}),n},_notify:function(e,t,n){if(!t.success&&this.config.loadErrorFn)this.config.loadErrorFn.call(this,this,e,t,n);else if(e){this.Env._missed&&this.Env._missed.length&&(t.msg="Missing modules: "+this.Env._missed.join(),t.success=!1);if(this.config.throwFail)e(this,t);else try{e(this,t)}catch(r){this.error("use callback error",r,n)}}},_use:function(e,t){this.Array||this._attach(["yui-base"]);var r,i,s,o,u=this,a=YUI.Env,f=a.mods,l=u.Env,c=l._used,h=a.aliases,p=a._loaderQueue,d=e[0],v=u.Array,m=u.config,g=m.bootstrap,y=[],b,E=[],S=!0,x=m.fetchCSS,T=function(e,t){var r=0,i=[],s,o,u,l,p;if(!e.length)return;if(h){o=e.length;for(r=0;r<o;r++)h[e[r]]&&!f[e[r]]?i=[].concat(i,h[e[r]]):i.push(e[r]);e=i}o=e.length;for(r=0;r<o;r++){s=e[r],t||E.push(s);if(c[s])continue;u=f[s],l=null,p=null,u?(c[s]=!0,l=u.details.requires,p=u.details.use):a._loaded[n][s]?c[s]=!0:y.push(s),l&&l.length&&T(l),p&&p.length&&T(p,1)}},N=function(n){var r=n||{success:!0,msg:"not dynamic"},i,s,o=!0,a=r.data;u._loading=!1,a&&(s=y,y=[],E=[],T(a),i=y.length,i&&[].concat(y).sort().join()==s.sort().join()&&(i=!1)),i&&a?(u._loading=!0,u._use(y,function(){u._attach(a)&&u._notify(t,r,a)})):(a&&(o=u._attach(a)),o&&u._notify(t,r,e)),u._useQueue&&u._useQueue.size()&&!u._loading&&u._use.apply(u,u._useQueue.next())};if(d==="*"){e=[];for(b in f)f.hasOwnProperty(b)&&e.push(b);return S=u._attach(e),S&&N(),u}return(f.loader||f["loader-base"])&&!u.Loader&&u._attach(["loader"+(f.loader?"":"-base")]),g&&u.Loader&&e.length&&(i=w(u),i.require(e),i.ignoreRegistered=!0,i._boot=!0,i.calculate(null,x?null:"js"),e=i.sorted,i._boot=!1),T(e),r=y.length,r&&(y=v.dedupe(y),r=y.length),g&&r&&u.Loader?(u._loading=!0,i=w(u),i.onEnd=N,i.context=u,i.data=e,i.ignoreRegistered=!1,i.require(e),i.insert(null,x?null:"js")):g&&r&&u.Get&&!l.bootstrapped?(u._loading=!0,s=function(){u._loading=!1,p.running=!1,l.bootstrapped=!0,a._bootstrapping=!1,u._attach(["loader"])&&u._use(e,t)},a._bootstrapping?p.add(s):(a._bootstrapping=!0,u.Get.script(m.base+m.loaderPath,{onEnd:s}))):(S=u._attach(e),S&&N()),u},namespace:function(){var e=arguments,t,n=0,i,s,o;for(;n<e.length;n++){t=this,o=e[n];if(o.indexOf(r)>-1){s=o.split(r);for(i=s[0]=="YAHOO"?1:0;i<s.length;i++)t[s[i]]=t[s[i]]||{},t=t[s[i]]}else t[o]=t[o]||{},t=t[o]}return t},log:u,message:u,dump:function(e){return""+e},error:function(e,t,n){var r=this,i;r.config.errorFn&&(i=r.config.errorFn.apply(r,arguments));if(!i)throw t||new Error(e);return r.message(e,"error",""+n),r},guid:function(e){var t=this.Env._guidp+"_"+ ++this.Env._uidx;return e?e+t:t},stamp:function(e,t){var n;if(!e)return e;e.uniqueID&&e.nodeType&&e.nodeType!==9?n=e.uniqueID:n=typeof e=="string"?e:e._yuid;if(!n){n=this.guid();if(!t)try{e._yuid=n}catch(r){n=null}}return n},destroy:function(){var e=this;e.Event&&e.Event._unload(),delete v[e.id],delete e.Env,delete e.config}},YUI.prototype=e;for(t in e)e.hasOwnProperty(t)&&(YUI[t]=e[t]);YUI.applyConfig=function(e){if(!e)return;YUI.GlobalConfig&&this.prototype.applyConfig.call(this,YUI.GlobalConfig),this.prototype.applyConfig.call(this,e),YUI.GlobalConfig=this.config},YUI._init(),l?g(window,"load",b):b(),YUI.Env.add=g,YUI.Env.remove=y,typeof exports=="object"&&(exports.YUI=YUI)})(),YUI.add("yui-base",function(e,t){function h(e,t,n){var r,i;t||(t=0);if(n||h.test(e))try{return l.slice.call(e,t)}catch(s){i=[];for(r=e.length;t<r;++t)i.push(e[t]);return i}return[e]}function p(){this._init(),this.add.apply(this,arguments)}var n=e.Lang||(e.Lang={}),r=String.prototype,i=Object.prototype.toString,s={"undefined":"undefined",number:"number","boolean":"boolean",string:"string","[object Function]":"function","[object RegExp]":"regexp","[object Array]":"array","[object Date]":"date","[object Error]":"error"},o=/\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,u=/^\s+|\s+$/g,a=/\{\s*\[(?:native code|function)\]\s*\}/i;n._isNative=function(t){return!!(e.config.useNativeES5&&t&&a.test(t))},n.isArray=n._isNative(Array.isArray)?Array.isArray:function(e){return n.type(e)==="array"},n.isBoolean=function(e){return typeof e=="boolean"},n.isDate=function(e){return n.type(e)==="date"&&e.toString()!=="Invalid Date"&&!isNaN(e)},n.isFunction=function(e){return n.type(e)==="function"},n.isNull=function(e){return e===null},n.isNumber=function(e){return typeof e=="number"&&isFinite(e)},n.isObject=function(e,t){var r=typeof e;return e&&(r==="object"||!t&&(r==="function"||n.isFunction(e)))||!1},n.isString=function(e){return typeof e=="string"},n.isUndefined=function(e){return typeof e=="undefined"},n.isValue=function(e){var t=n.type(e);switch(t){case"number":return isFinite(e);case"null":case"undefined":return!1;default:return!!t}},n.now=Date.now||function(){return(new Date).getTime()},n.sub=function(e,t){return e.replace?e.replace(o,function(e,r){return n.isUndefined(t[r])?e:t[r]}):e},n.trim=r.trim?function(e){return e&&e.trim?e.trim():e}:function(e){try{return e.replace(u,"")}catch(t){return e}},n.trimLeft=r.trimLeft?function(e){return e.trimLeft()}:function(e){return e.replace(/^\s+/,"")},n.trimRight=r.trimRight?function(e){return e.trimRight()}:function(e){return e.replace(/\s+$/,"")},n.type=function(e){return s[typeof e]||s[i.call(e)]||(e?"object":"null")};var f=e.Lang,l=Array.prototype,c=Object.prototype.hasOwnProperty;e.Array=h,h.dedupe=function(e){var t={},n=[],r,i,s;for(r=0,s=e.length;r<s;++r)i=e[r],c.call(t,i)||(t[i]=1,n.push(i));return n},h.each=h.forEach=f._isNative(l.forEach)?function(t,n,r){return l.forEach.call(t||[],n,r||e),e}:function(t,n,r){for(var i=0,s=t&&t.length||0;i<s;++i)i in t&&n.call(r||e,t[i],i,t);return e},h.hash=function(e,t){var n={},r=t&&t.length||0,i,s;for(i=0,s=e.length;i<s;++i)i in e&&(n[e[i]]=r>i&&i in t?t[i]:!0);return n},h.indexOf=f._isNative(l.indexOf)?function(e,t,n){return l.indexOf.call(e,t,n)}:function(e,t,n){var r=e.length;n=+n||0,n=(n>0||-1)*Math.floor(Math.abs(n)),n<0&&(n+=r,n<0&&(n=0));for(;n<r;++n)if(n in e&&e[n]===t)return n;return-1},h.numericSort=function(e,t){return e-t},h.some=f._isNative(l.some)?function(e,t,n){return l.some.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&t.call(n,e[r],r,e))return!0;return!1},h.test=function(e){var t=0;if(f.isArray(e))t=1;else if(f.isObject(e))try{"length"in e&&!e.tagName&&(!e.scrollTo||!e.document)&&!e.apply&&(t=2)}catch(n){}return t},p.prototype={_init:function(){this._q=[]},next:function(){return this._q.shift()},last:function(){return this._q.pop()},add:function(){return this._q.push.apply(this._q,arguments),this},size:function(){return this._q.length}},e.Queue=p,YUI.Env._loaderQueue=YUI.Env._loaderQueue||new p;var d="__",c=Object.prototype.hasOwnProperty,v=e.Lang.isObject;e.cached=function(e,t,n){return t||(t={}),function(r){var i=arguments.length>1?Array.prototype.join.call(arguments,d):String(r);if(!(i in t)||n&&t[i]==n)t[i]=e.apply(e,arguments);return t[i]}},e.getLocation=function(){var t=e.config.win;return t&&t.location},e.merge=function(){var e=0,t=arguments.length,n={},r,i;for(;e<t;++e){i=arguments[e];for(r in i)c.call(i,r)&&(n[r]=i[r])}return n},e.mix=function(t,n,r,i,s,o){var u,a,f,l,h,p,d;if(!t||!n)return t||e;if(s){s===2&&e.mix(t.prototype,n.prototype,r,i,0,o),f=s===1||s===3?n.prototype:n,d=s===1||s===4?t.prototype:t;if(!f||!d)return t}else f=n,d=t;u=r&&!o;if(i)for(l=0,p=i.length;l<p;++l){h=i[l];if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}else{for(h in f){if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}e.Object._hasEnumBug&&e.mix(d,f,r,e.Object._forceEnum,s,o)}return t};var f=e.Lang,c=Object.prototype.hasOwnProperty,m,g=e.Object=f._isNative(Object.create)?function(e){return Object.create(e)}:function(){function e(){}return function(t){return e.prototype=t,new e}}(),y=g._forceEnum=["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf"],b=g._hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),w=g._hasProtoEnumBug=function(){}.propertyIsEnumerable("prototype"),E=g.owns=function(e,t){return!!e&&c.call(e,t)};g.hasKey=E,g.keys=f._isNative(Object.keys)?Object.keys:function(e){if(!f.isObject(e))throw new TypeError("Object.keys called on a non-object");var t=[],n,r,i;if(w&&typeof e=="function")for(r in e)E(e,r)&&r!=="prototype"&&t.push(r);else for(r in e)E(e,r)&&t.push(r);if(b)for(n=0,i=y.length;n<i;++n)r=y[n],E(e,r)&&t.push(r);return t},g.values=function(e){var t=g.keys(e),n=0,r=t.length,i=[];for(;n<r;++n)i.push(e[t[n]]);return i},g.size=function(e){try{return g.keys(e).length}catch(t){return 0}},g.hasValue=function(t,n){return e.Array.indexOf(g.values(t),n)>-1},g.each=function(t,n,r,i){var s;for(s in t)(i||E(t,s))&&n.call(r||e,t[s],s,t);return e},g.some=function(t,n,r,i){var s;for(s in t)if(i||E(t,s))if(n.call(r||e,t[s],s,t))return!0;return!1},g.getValue=function(t,n){if(!f.isObject(t))return m;var r,i=e.Array(n),s=i.length;for(r=0;t!==m&&r<s;r++)t=t[i[r]];return t},g.setValue=function(t,n,r){var i,s=e.Array(n),o=s.length-1,u=t;if(o>=0){for(i=0;u!==m&&i<o;i++)u=u[s[i]];if(u===m)return m;u[s[i]]=r}return t},g.isEmpty=function(e){return!g.keys(Object(e)).length},YUI.Env.parseUA=function(t){var n=function(e){var t=0;return parseFloat(e.replace(/\./g,function(){return t++===1?"":"."}))},r=e.config.win,i=r&&r.navigator,s={ie:0,opera:0,gecko:0,webkit:0,safari:0,chrome:0,mobile:null,air:0,phantomjs:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,silk:0,accel:!1,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null,nodejs:0,winjs:typeof Windows!="undefined"&&!!Windows.System,touchEnabled:!1},o=t||i&&i.userAgent,u=r&&r.location,a=u&&u.href,f;return s.userAgent=o,s.secure=a&&a.toLowerCase().indexOf("https")===0,o&&(/windows|win32/i.test(o)?s.os="windows":/macintosh|mac_powerpc/i.test(o)?s.os="macintosh":/android/i.test(o)?s.os="android":/symbos/i.test(o)?s.os="symbos":/linux/i.test(o)?s.os="linux":/rhino/i.test(o)&&(s.os="rhino"),/KHTML/.test(o)&&(s.webkit=1),/IEMobile|XBLWP7/.test(o)&&(s.mobile="windows"),/Fennec/.test(o)&&(s.mobile="gecko"),f=o.match(/AppleWebKit\/([^\s]*)/),f&&f[1]&&(s.webkit=n(f[1]),s.safari=s.webkit,/PhantomJS/.test(o)&&(f=o.match(/PhantomJS\/([^\s]*)/),f&&f[1]&&(s.phantomjs=n(f[1]))),/ Mobile\//.test(o)||/iPad|iPod|iPhone/.test(o)?(s.mobile="Apple",f=o.match(/OS ([^\s]*)/),f&&f[1]&&(f=n(f[1].replace("_","."))),s.ios=f,s.os="ios",s.ipad=s.ipod=s.iphone=0,f=o.match(/iPad|iPod|iPhone/),f&&f[0]&&(s[f[0].toLowerCase()]=s.ios)):(f=o.match(/NokiaN[^\/]*|webOS\/\d\.\d/),f&&(s.mobile=f[0]),/webOS/.test(o)&&(s.mobile="WebOS",f=o.match(/webOS\/([^\s]*);/),f&&f[1]&&(s.webos=n(f[1]))),/ Android/.test(o)&&(/Mobile/.test(o)&&(s.mobile="Android"),f=o.match(/Android ([^\s]*);/),f&&f[1]&&(s.android=n(f[1]))),/Silk/.test(o)&&(f=o.match(/Silk\/([^\s]*)\)/),f&&f[1]&&(s.silk=n(f[1])),s.android||(s.android=2.34,s.os="Android"),/Accelerated=true/.test(o)&&(s.accel=!0))),f=o.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/),f&&f[1]&&f[2]?(s.chrome=n(f[2]),s.safari=0,f[1]==="CrMo"&&(s.mobile="chrome")):(f=o.match(/AdobeAIR\/([^\s]*)/),f&&(s.air=f[0]))),s.webkit||(/Opera/.test(o)?(f=o.match(/Opera[\s\/]([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),f=o.match(/Version\/([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),/Opera Mobi/.test(o)&&(s.mobile="opera",f=o.replace("Opera Mobi","").match(/Opera ([^\s]*)/),f&&f[1]&&(s.opera=n(f[1]))),f=o.match(/Opera Mini[^;]*/),f&&(s.mobile=f[0])):(f=o.match(/MSIE\s([^;]*)/),f&&f[1]?s.ie=n(f[1]):(f=o.match(/Gecko\/([^\s]*)/),f&&(s.gecko=1,f=o.match(/rv:([^\s\)]*)/),f&&f[1]&&(s.gecko=n(f[1]))))))),r&&i&&!(s.chrome&&s.chrome<6)&&(s.touchEnabled="ontouchstart"in r||"msMaxTouchPoints"in i&&i.msMaxTouchPoints>0),t||(typeof process=="object"&&process.versions&&process.versions.node&&(s.os=process.platform,s.nodejs=n(process.versions.node)),YUI.Env.UA=s),s},e.UA=YUI.Env.UA||YUI.Env.parseUA(),e.UA.compareVersions=function(e,t){var n,r,i,s,o,u;if(e===t)return 0;r=(e+"").split("."),s=(t+"").split(".");for(o=0,u=Math.max(r.length,s.length);o<u;++o){n=parseInt(r[o],10),i=parseInt(s[o],10),isNaN(n)&&(n=0),isNaN(i)&&(i=0);if(n<i)return-1;if(n>i)return 1}return 0},YUI.Env.aliases={anim:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],"anim-shape-transform":["anim-shape"],app:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],attribute:["attribute-base","attribute-complex"],autocomplete:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],base:["base-base","base-pluginhost","base-build"],cache:["cache-base","cache-offline","cache-plugin"],collection:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],controller:["router"],dataschema:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],datasource:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],datatable:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],"datatable-deprecated":["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],datatype:["datatype-date","datatype-number","datatype-xml"],"datatype-date":["datatype-date-parse","datatype-date-format","datatype-date-math"],"datatype-number":["datatype-number-parse","datatype-number-format"],"datatype-xml":["datatype-xml-parse","datatype-xml-format"],dd:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],dom:["dom-base","dom-screen","dom-style","selector-native","selector"],editor:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],event:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],"event-custom":["event-custom-base","event-custom-complex"],"event-gestures":["event-flick","event-move"],handlebars:["handlebars-compiler"],highlight:["highlight-base","highlight-accentfold"],history:["history-base","history-hash","history-hash-ie","history-html5"],io:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],json:["json-parse","json-stringify"],loader:["loader-base","loader-rollup","loader-yui3"],node:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],pluginhost:["pluginhost-base","pluginhost-config"],querystring:["querystring-parse","querystring-stringify"],recordset:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],resize:["resize-base","resize-proxy","resize-constrain"],slider:["slider-base","slider-value-range","clickable-rail","range-slider"],text:["text-accentfold","text-wordbreak"],widget:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]}},"3.7.3",{use:["yui-base","get","features","intl-base","yui-log","yui-log-nodejs","yui-later","loader-base","loader-rollup","loader-yui3"]}),YUI.add("get",function(e,t){var n=require("path"),r=require("vm"),i=require("fs"),s=require("request"),o=i.existsSync||n.existsSync;e.Get=function(){},e.config.base=n.join(__dirname,"../"),YUI.require=require,YUI.process=process;var u=function(e){return e.replace(/\\/g,"\\\\")};e.Get._exec=function(e,t,i){var s=u(n.dirname(t)),o=u(t);s.match(/^https?:\/\//)&&(s=".",o="remoteResource");var a="(function(YUI) { var __dirname = '"+s+"'; "+"var __filename = '"+o+"'; "+"var process = YUI.process;"+"var require = function(file) {"+" if (file.indexOf('./') === 0) {"+" file = __dirname + file.replace('./', '/'); }"+" return YUI.require(file); }; "+e+" ;return YUI; })",f=r.createScript(a,t),l=f.runInThisContext(a);YUI=l(YUI),i(null,t)},e.Get._include=function(t,n){var r=this;if(t.match(/^https?:\/\//)){var u={url:t,timeout:r.timeout};s(u,function(r,i,s){r?n(r,t):e.Get._exec(s,t,n)})}else if(e.config.useSync)if(o(t)){var a=i.readFileSync(t,"utf8");e.Get._exec(a,t,n)}else n("Path does not exist: "+t,t);else i.readFile(t,"utf8",function(r,i){r?n(r,t):e.Get._exec(i,t,n)})};var a=function(t,n,r){e.Lang.isFunction(t.onEnd)&&t.onEnd.call(e,n,r)},f=function(t){e.Lang.isFunction(t.onSuccess)&&t.onSuccess.call(e,t),a(t,"success","success")},l=function(t,n){n.errors=[n],e.Lang.isFunction(t.onFailure)&&t.onFailure.call(e,n,t),a(t,n,"fail")};e.Get.js=function(t,n){var r=e.Array,i=this,s=r(t),o,u,a=s.length,c=0,h=function(){c===a&&f(n)};for(u=0;u<a;u++)o=s[u],e.Lang.isObject(o)&&(o=o.url),o=o.replace(/'/g,"%27"),e.Get._include(o,function(t,r){e.config||(e.config={debug:!0}),n.onProgress&&n.onProgress.call(n.context||e,r),t?l(n,t):(c++,h())})},e.Get.script=e.Get.js,e.Get.css=function(e,t){f(t)}},"3.7.3"),YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]}),YUI.add("intl-base",function(e,t){var n=/[, ]/;e.mix(e.namespace("Intl"),{lookupBestLang:function(t,r){function a(e){var t;for(t=0;t<r.length;t+=1)if(e.toLowerCase()===r[t].toLowerCase())return r[t]}var i,s,o,u;e.Lang.isString(t)&&(t=t.split(n));for(i=0;i<t.length;i+=1){s=t[i];if(!s||s==="*")continue;while(s.length>0){o=a(s);if(o)return o;u=s.lastIndexOf("-");if(!(u>=0))break;s=s.substring(0,u),u>=2&&s.charAt(u-2)==="-"&&(s=s.substring(0,u-2))}}return""}})},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-log-nodejs",function(e,t){var n=require(process.binding("natives").util?"util":"sys"),r=!1;try{var i=require("stdio");r=i.isStderrATTY()}catch(s){r=!0}e.config.useColor=r,e.consoleColor=function(e,t){return this.config.useColor?(t||(t="32"),"["+t+"m"+e+""):e};var o=function(e,t,r){var i="";this.id&&(i="["+this.id+"]:"),t=t||"info",r=r?this.consoleColor(" ("+r.toLowerCase()+"):",35):"",e===null&&(e="null");if(typeof e=="object"||e instanceof Array)try{e.tagName||e._yuid||e._query?e=e.toString():e=n.inspect(e)}catch(s){}var o="37;40",u=e?"":31;t+="";switch(t.toLowerCase()){case"error":o=u=31;break;case"warn":o=33;break;case"debug":o=34}typeof e=="string"&&e&&e.indexOf("\n")!==-1&&(e="\n"+e),n.error(this.consoleColor(t.toLowerCase()+":",o)+r+" "+this.consoleColor(e,u))};e.config.logFn||(e.config.logFn=o)},"3.7.3"),YUI.add("yui-later",function(e,t){var n=[];e.later=function(t,r,i,s,o){t=t||0,s=e.Lang.isUndefined(s)?n:e.Array(s),r=r||e.config.win||e;var u=!1,a=r&&e.Lang.isString(i)?r[i]:i,f=function(){u||(a.apply?a.apply(r,s||n):a(s[0],s[1],s[2],s[3]))},l=o?setInterval(f,t):setTimeout(f,t);return{id:l,interval:o,cancel:function(){u=!0,this.interval?clearInterval(l):clearTimeout(l)}}},e.Lang.later=e.later},"3.7.3",{requires:["yui-base"]}),YUI.add("loader-base",function(e,t){YUI.Env[e.version]||function(){var t=e.version,n="/build/",r=t+n,i=e.Env.base,s="gallery-2012.10.10-19-59",o="2in3",u="4",a="2.9.0",f=i+"combo?",l={version:t,root:r,base:e.Env.base,comboBase:f,skin:{defaultSkin:"sam",base:"assets/skins/",path:"skin.css",after:["cssreset","cssfonts","cssgrids","cssbase","cssreset-context","cssfonts-context"]},groups:{},patterns:{}},c=l.groups,h=function(e,t,r){var s=o+"."+(e||u)+"/"+(t||a)+n,l=r&&r.base?r.base:i,h=r&&r.comboBase?r.comboBase:f;c.yui2.base=l+s,c.yui2.root=s,c.yui2.comboBase=h},p=function(e,t){var r=(e||s)+n,o=t&&t.base?t.base:i,u=t&&t.comboBase?t.comboBase:f;c.gallery.base=o+r,c.gallery.root=r,c.gallery.comboBase=u};c[t]={},c.gallery={ext:!1,combine:!0,comboBase:f,update:p,patterns:{"gallery-":{},"lang/gallery-":{},"gallerycss-":{type:"css"}}},c.yui2={combine:!0,ext:!1,comboBase:f,update:h,patterns:{"yui2-":{configFn:function(e){/-skin|reset|fonts|grids|base/.test(e.name)&&(e.type="css",e.path=e.path.replace(/\.js/,".css"),e.path=e.path.replace(/\/yui2-skin/,"/assets/skins/sam/yui2-skin"))}}}},p(),h(),YUI.Env[t]=l}();var n={},r=[],i=1024,s=YUI.Env,o=s._loaded,u="css",a="js",f="intl",l="sam",c=e.version,h="",p=e.Object,d=p.each,v=e.Array,m=s._loaderQueue,g=s[c],y="skin-",b=e.Lang,w=s.mods,E,S=function(e,t,n,r){var i=e+"/"+t;return r||(i+="-min"),i+="."+(n||u),i};YUI.Env._cssLoaded||(YUI.Env._cssLoaded={}),e.Env.meta=g,e.Loader=function(t){var n=this;t=t||{},E=g.md5,n.context=e,n.base=e.Env.meta.base+e.Env.meta.root,n.comboBase=e.Env.meta.comboBase,n.combine=t.base&&t.base.indexOf(n.comboBase.substr(0,20))>-1,n.comboSep="&",n.maxURLLength=i,n.ignoreRegistered=t.ignoreRegistered,n.root=e.Env.meta.root,n.timeout=0,n.forceMap={},n.allowRollup=!1,n.filters={},n.required={},n.patterns={},n.moduleInfo={},n.groups=e.merge(e.Env.meta.groups),n.skin=e.merge(e.Env.meta.skin),n.conditions={},n.config=t,n._internal=!0,n._populateCache(),n.loaded=o[c],n.async=!0,n._inspectPage(),n._internal=!1,n._config(t),n.forceMap=n.force?e.Array.hash(n.force):{},n.testresults=null,e.config.tests&&(n.testresults=e.config.tests),n.sorted=[],n.dirty=!0,n.inserted={},n.skipped={},n.tested={},n.ignoreRegistered&&n._resetModules()},e.Loader.prototype={_populateCache:function(){var t=this,n=g.modules,r=s._renderedMods,i;if(r&&!t.ignoreRegistered){for(i in r)r.hasOwnProperty(i)&&(t.moduleInfo[i]=e.merge(r[i]));r=s._conditions;for(i in r)r.hasOwnProperty(i)&&(t.conditions[i]=e.merge(r[i]))}else for(i in n)n.hasOwnProperty(i)&&t.addModule(n[i],i)},_resetModules:function(){var e=this,t,n,r,i,s;for(t in e.moduleInfo)if(e.moduleInfo.hasOwnProperty(t)){r=e.moduleInfo[t],i=r.name,s=YUI.Env.mods[i]?YUI.Env.mods[i].details:null,s&&(e.moduleInfo[i]._reset=!0,e.moduleInfo[i].requires=s.requires||[],e.moduleInfo[i].optional=s.optional||[],e.moduleInfo[i].supersedes=s.supercedes||[]);if(r.defaults)for(n in r.defaults)r.defaults.hasOwnProperty(n)&&r[n]&&(r[n]=r.defaults[n]);delete r.langCache,delete r.skinCache,r.skinnable&&e._addSkin(e.skin.defaultSkin,r.name)}},REGEX_CSS:/\.css(?:[?;].*)?$/i,FILTER_DEFS:{RAW:{searchExp:"-min\\.js",replaceStr:".js"},DEBUG:{searchExp:"-min\\.js",replaceStr:"-debug.js"},COVERAGE:{searchExp:"-min\\.js",replaceStr:"-coverage.js"}},_inspectPage:function(){var e=this,t,n,r,i,s;for(s in e.moduleInfo)e.moduleInfo.hasOwnProperty(s)&&(t=e.moduleInfo[s],t.type&&t.type===u&&e.isCSSLoaded(t.name)&&(e.loaded[s]=!0));for(s in w)w.hasOwnProperty(s)&&(t=w[s],t.details&&(n=e.moduleInfo[t.name],r=t.details.requires,i=n&&n.requires,n?!n._inspected&&r&&i.length!==r.length&&delete n.expanded:n=e.addModule(t.details,s),n._inspected=!0))},_requires:function(e,t){var n,r,i,s,o=this.moduleInfo,a=o[e],f=o[t];if(!a||!f)return!1;r=a.expanded_map,i=a.after_map;if(i&&t in i)return!0;i=f.after_map;if(i&&e in i)return!1;s=o[t]&&o[t].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(e,s[n]))return!0;s=o[e]&&o[e].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(t,s[n]))return!1;return r&&t in r?!0:a.ext&&a.type===u&&!f.ext&&f.type===u?!0:!1},_config:function(t){var n,r,i,s,o,u,a,f=this,l=[],c;if(t)for(n in t)if(t.hasOwnProperty(n)){i=t[n];if(n==="require")f.require(i);else if(n==="skin")typeof i=="string"&&(f.skin.defaultSkin=t.skin,i={defaultSkin:i}),e.mix(f.skin,i,!0);else if(n==="groups"){for(r in i)if(i.hasOwnProperty(r)){a=r,u=i[r],f.addGroup(u,a);if(u.aliases)for(s in u.aliases)u.aliases.hasOwnProperty(s)&&f.addAlias(u.aliases[s],s)}}else if(n==="modules")for(r in i)i.hasOwnProperty(r)&&f.addModule(i[r],r);else if(n==="aliases")for(r in i)i.hasOwnProperty(r)&&f.addAlias(i[r],r);else n==="gallery"?this.groups.gallery.update(i,t):n==="yui2"||n==="2in3"?this.groups.yui2.update(t["2in3"],t.yui2,t):f[n]=i}o=f.filter,b.isString(o)&&(o=o.toUpperCase(),f.filterName=o,f.filter=f.FILTER_DEFS[o],o==="DEBUG"&&f.require("yui-log","dump"));if(f.filterName&&f.coverage&&f.filterName==="COVERAGE"&&b.isArray(f.coverage)&&f.coverage.length){for(n=0;n<f.coverage.length;n++)c=f.coverage[n],f.moduleInfo[c]&&f.moduleInfo[c].use?l=[].concat(l,f.moduleInfo[c].use):l.push(c);f.filters=f.filters||{},e.Array.each(l,function(e){f.filters[e]=f.FILTER_DEFS.COVERAGE}),f.filterName="RAW",f.filter=f.FILTER_DEFS[f.filterName]}},formatSkin:function(e,t){var n=y+e;return t&&(n=n+"-"+t),n},_addSkin:function(e,t,n){var r,i,s,o,u=this.moduleInfo,a=this.skin,f=u[t]&&u[t].ext;return t&&(s=this.formatSkin(e,t),u[s]||(r=u[t],i=r.pkg||t,o={skin:!0,name:s,group:r.group,type:"css",after:a.after,path:(n||i)+"/"+a.base+e+"/"+t+".css",ext:f},r.base&&(o.base=r.base),r.configFn&&(o.configFn=r.configFn),this.addModule(o,s))),s},addAlias:function(e,t){YUI.Env.aliases[t]=e,this.addModule({name:t,use:e})},addGroup:function(e,t){var n=e.modules,r=this,i,s;t=t||e.name,e.name=t,r.groups[t]=e;if(e.patterns)for(i in e.patterns)e.patterns.hasOwnProperty(i)&&(e.patterns[i].group=t,r.patterns[i]=e.patterns[i]);if(n)for(i in n)n.hasOwnProperty(i)&&(s=n[i],typeof s=="string"&&(s={name:i,fullpath:s}),s.group=t,r.addModule(s,i))},addModule:function(t,n){n=n||t.name,typeof t=="string"&&(t={name:n,fullpath:t});var r,i,o,f,l,c,p,d,m,g,y,b,w,E,x,T,N,C,k,L,A,O,M=this.conditions,_;this.moduleInfo[n]&&this.moduleInfo[n].temp&&(t=e.merge(this.moduleInfo[n],t)),t.name=n;if(!t||!t.name)return null;t.type||(t.type=a,O=t.path||t.fullpath,O&&this.REGEX_CSS.test(O)&&(t.type=u)),!t.path&&!t.fullpath&&(t.path=S(n,n,t.type)),t.supersedes=t.supersedes||t.use,t.ext="ext"in t?t.ext:this._internal?!1:!0,r=t.submodules,this.moduleInfo[n]=t,t.requires=t.requires||[];if(this.requires)for(i=0;i<this.requires.length;i++)t.requires.push(this.requires[i]);if(t.group&&this.groups&&this.groups[t.group]){A=this.groups[t.group];if(A.requires)for(i=0;i<A.requires.length;i++)t.requires.push(A.requires[i])}t.defaults||(t.defaults={requires:t.requires?[].concat(t.requires):null,supersedes:t.supersedes?[].concat(t.supersedes):null,optional:t.optional?[].concat(t.optional):null}),t.skinnable&&t.ext&&t.temp&&(k=this._addSkin(this.skin.defaultSkin,n),t.requires.unshift(k)),t.requires.length&&(t.requires=this.filterRequires(t.requires)||[]);if(!t.langPack&&t.lang){y=v(t.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b))}if(r){l=t.supersedes||[],o=0;for(i in r)if(r.hasOwnProperty(i)){c=r[i],c.path=c.path||S(n,i,t.type),c.pkg=n,c.group=t.group,c.supersedes&&(l=l.concat(c.supersedes)),p=this.addModule(c,i),l.push(i);if(p.skinnable){t.skinnable=!0,C=this.skin.overrides;if(C&&C[i])for(g=0;g<C[i].length;g++)k=this._addSkin(C[i][g],i,n),l.push(k);k=this._addSkin(this.skin.defaultSkin,i,n),l.push(k)}if(c.lang&&c.lang.length){y=v(c.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),w=this.getLangPackName(T,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),E=E||v.hash(p.supersedes),w in E||p.supersedes.push(w),t.lang=t.lang||[],x=x||v.hash(t.lang),T in x||t.lang.push(T),b=this.getLangPackName(h,n),w=this.getLangPackName(h,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),w in E||p.supersedes.push(w)}o++}t.supersedes=v.dedupe(l),this.allowRollup&&(t.rollup=o<4?o:Math.min(o-1,4))}d=t.plugins;if(d)for(i in d)d.hasOwnProperty(i)&&(m=d[i],m.pkg=n,m.path=m.path||S(n,i,t.type),m.requires=m.requires||[],m.group=t.group,this.addModule(m,i),t.skinnable&&this._addSkin(this.skin.defaultSkin,i,n));if(t.condition){f=t.condition.trigger,YUI.Env.aliases[f]&&(f=YUI.Env.aliases[f]),e.Lang.isArray(f)||(f=[f]);for(i=0;i<f.length;i++)_=f[i],L=t.condition.when,M[_]=M[_]||{},M[_][n]=t.condition,L&&L!=="after"?L==="instead"&&(t.supersedes=t.supersedes||[],t.supersedes.push(_)):(t.after=t.after||[],t.after.push(_))}return t.supersedes&&(t.supersedes=this.filterRequires(t.supersedes)),t.after&&(t.after=this.filterRequires(t.after),t.after_map=v.hash(t.after)),t.configFn&&(N=t.configFn(t),N===!1&&(delete this.moduleInfo[n],delete s._renderedMods[n],t=null)),t&&(s._renderedMods||(s._renderedMods={}),s._renderedMods[n]=e.mix(s._renderedMods[n]||{},t),s._conditions=M),t},require:function(t){var n=typeof t=="string"?v(arguments):t;this.dirty=!0,this.required=e.merge(this.required,v.hash(this.filterRequires(n))),this._explodeRollups()},_explodeRollups:function(){var e=this,t,n,r,i,s,o,u,a=e.required;if(!e.allowRollup){for(r in a)if(a.hasOwnProperty(r)){t=e.getModule(r);if(t&&t.use){o=t.use.length;for(i=0;i<o;i++){n=e.getModule(t.use[i]);if(n&&n.use){u=n.use.length;for(s=0;s<u;s++)a[n.use[s]]=!0}else a[t.use[i]]=!0}}}e.required=a}},filterRequires:function(t){if(t){e.Lang.isArray(t)||(t=[t]),t=e.Array(t);var n=[],r,i,s,o;for(r=0;r<t.length;r++){i=this.getModule(t[r]);if(i&&i.use)for(s=0;s<i.use.length;s++)o=this.getModule(i.use[s]),o&&o.use&&o.name!==i.name?n=e.Array.dedupe([].concat(n,this.filterRequires(o.use))):n.push(i.use[s]);else n.push(t[r])}t=n}return t},getRequires:function(t){if(!t)return r;if(t._parsed)return t.expanded||r;var n,i,s,o,u,a,l=this.testresults,c=t.name,m,g=w[c]&&w[c].details,y,b,E,S,x,T,N,C,k,L,A=t.lang||t.intl,O=this.moduleInfo,M=e.Features&&e.Features.tests.load,_,D;t.temp&&g&&(x=t,t=this.addModule(g,c),t.group=x.group,t.pkg=x.pkg,delete t.expanded),D=!!this.lang&&t.langCache!==this.lang||t.skinCache!==this.skin.defaultSkin;if(t.expanded&&!D)return t.expanded;y=[],_={},S=this.filterRequires(t.requires),t.lang&&(y.unshift("intl"),S.unshift("intl"),A=!0),T=this.filterRequires(t.optional),t._parsed=!0,t.langCache=this.lang,t.skinCache=this.skin.defaultSkin;for(n=0;n<S.length;n++)if(!_[S[n]]){y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}S=this.filterRequires(t.supersedes);if(S)for(n=0;n<S.length;n++)if(!_[S[n]]){t.submodules&&y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}if(T&&this.loadOptional)for(n=0;n<T.length;n++)if(!_[T[n]]){y.push(T[n]),_[T[n]]=!0,i=O[T[n]];if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}m=this.conditions[c];if(m){t._parsed=!1;if(l&&M)d(l,function(e,t){var n=M[t].name;!_[n]&&M[t].trigger===c&&e&&M[t]&&(_[n]=!0,y.push(n))});else for(n in m)if(m.hasOwnProperty(n)&&!_[n]){E=m[n],b=E&&(!E.ua&&!E.test||E.ua&&e.UA[E.ua]||E.test&&E.test(e,S));if(b){_[n]=!0,y.push(n),i=this.getModule(n);if(i){o=this.getRequires(i);for(s=0;s<o.length;s++)y.push(o[s])}}}}if(t.skinnable){C=this.skin.overrides;for(n in YUI.Env.aliases)YUI.Env.aliases.hasOwnProperty(n)&&e.Array.indexOf(YUI.Env.aliases[n],c)>-1&&(k=n);if(C&&(C[c]||k&&C[k])){L=c,C[k]&&(L=k);for(n=0;n<C[L].length;n++)N=this._addSkin(C[L][n],c),this.isCSSLoaded(N,this._boot)||y.push(N)}else N=this._addSkin(this.skin.defaultSkin,c),this.isCSSLoaded(N,this._boot)||y.push(N)}return t._parsed=!1,A&&(t.lang&&!t.langPack&&e.Intl&&(a=e.Intl.lookupBestLang(this.lang||h,t.lang),u=this.getLangPackName(a,c),u&&y.unshift(u)),y.unshift(f)),t.expanded_map=v.hash(y),t.expanded=p.keys(t.expanded_map),t.expanded},isCSSLoaded:function(t,n){if(!t||!YUI.Env.cssStampEl||!n&&this.ignoreRegistered)return!1;var r=YUI.Env.cssStampEl,i=!1,s=YUI.Env._cssLoaded[t],o=r.currentStyle;return s!==undefined?s:(r.className=t,o||(o=e.config.doc.defaultView.getComputedStyle(r,null)),o&&o.display==="none"&&(i=!0),r.className="",YUI.Env._cssLoaded[t]=i,i)},getProvides:function(t){var r=this.getModule(t),i,s;return r?(r&&!r.provides&&(i={},s=r.supersedes,s&&v.each(s,function(t){e.mix(i,this.getProvides(t))},this),i[t]=!0,r.provides=i),r.provides):n},calculate:function(e,t){if(e||t||this.dirty)e&&this._config(e),this._init||this._setup(),this._explode(),this.allowRollup?this._rollup():this._explodeRollups(),this._reduce(),this._sort()},_addLangPack:function(t,n,r){var i=n.name,s,o,u=this.moduleInfo[r];return u||(s=S(n.pkg||i,r,a,!0),o={path:s,intl:!0,langPack:!0,ext:n.ext,group:n.group,supersedes:[]},n.root&&(o.root=n.root),n.base&&(o.base=n.base),n.configFn&&(o.configFn=n.configFn),this.addModule(o,r),t&&(e.Env.lang=e.Env.lang||{},e.Env.lang[t]=e.Env.lang[t]||{},e.Env.lang[t][i]=!0)),this.moduleInfo[r]},_setup:function(){var t=this.moduleInfo,n,r,i,o,u,a;for(n in t)t.hasOwnProperty(n)&&(o=t[n],o&&(o.requires=v.dedupe(o.requires),o.lang&&(a=this.getLangPackName(h,n),this._addLangPack(null,o,a))));u={},this.ignoreRegistered||e.mix(u,s.mods),this.ignore&&e.mix(u,v.hash(this.ignore));for(i in u)u.hasOwnProperty(i)&&e.mix(u,this.getProvides(i));if(this.force)for(r=0;r<this.force.length;r++)this.force[r]in u&&delete u[this.force[r]];e.mix(this.loaded,u),this._init=!0},getLangPackName:function(e,t){return"lang/"+t+(e?"_"+e:"")},_explode:function(){var t=this.required,n,r,i={},s=this,o,u;s.dirty=!1,s._explodeRollups(),t=s.required;for(o in t)t.hasOwnProperty(o)&&(i[o]||(i[o]=!0,n=s.getModule(o),n&&(u=n.expound,u&&(t[u]=s.getModule(u),r=s.getRequires(t[u]),e.mix(t,v.hash(r))),r=s.getRequires(n),e.mix(t,v.hash(r)))))},_patternTest:function(e,t){return e.indexOf(t)>-1},getModule:function(t){if(!t)return null;var n,r,i,s=this.moduleInfo[t],o=this.patterns;if(!s||s&&s.ext)for(i in o)if(o.hasOwnProperty(i)){n=o[i],n.test||(n.test=this._patternTest);if(n.test(t,i)){r=n;break}}return s?r&&s&&r.configFn&&!s.configFn&&(s.configFn=r.configFn,s.configFn(s)):r&&(n.action?n.action.call(this,t,i):(s=this.addModule(e.merge(r),t),r.configFn&&(s.configFn=r.configFn),s.temp=!0)),s},_rollup:function(){},_reduce:function(e){e=e||this.required;var t,n,r,i,s=this.loadType,o=this.ignore?v.hash(this.ignore):!1;for(t in e)if(e.hasOwnProperty(t)){i=this.getModule(t),((this.loaded[t]||w[t])&&!this.forceMap[t]&&!this.ignoreRegistered||s&&i&&i.type!==s)&&delete e[t],o&&o[t]&&delete e[t],r=i&&i.supersedes;if(r)for(n=0;n<r.length;n++)r[n]in e&&delete e[r[n]]}return e},_finish:function(e,t){m.running=!1;var n=this.onEnd;n&&n.call(this.context,{msg:e,data:this.data,success:t}),this._continue()},_onSuccess:function(){var t=this,n=e.merge(t.skipped),r,i=[],s=t.requireRegistration,o,u,f,l;for(f in n)n.hasOwnProperty(f)&&delete t.inserted[f];t.skipped={};for(f in t.inserted)t.inserted.hasOwnProperty(f)&&(l=t.getModule(f),!l||!s||l.type!==a||f in YUI.Env.mods?e.mix(t.loaded,t.getProvides(f)):i.push(f));r=t.onSuccess,u=i.length?"notregistered":"success",o=!i.length,r&&r.call(t.context,{msg:u,data:t.data,success:o,failed:i,skipped:n}),t._finish(u,o)},_onProgress:function(e){var t=this,n;if(e.data&&e.data.length)for(n=0;n<e.data.length;n++)e.data[n]=t.getModule(e.data[n].name);t.onProgress&&t.onProgress.call(t.context,{name:e.url,data:e.data})},_onFailure:function(e){var t=this.onFailure,n=[],r=0,i=e.errors.length;for(r;r<i;r++)n.push(e.errors[r].error);n=n.join(","),t&&t.call(this.context,{msg:n,data:this.data,success:!1}),this._finish(n,!1)},_onTimeout:function(){var e=this.onTimeout;e&&e.call(this.context,{msg:"timeout",data:this.data,success:!1})},_sort:function(){var e=p.keys(this.required),t={},n=0,r,i,s,o,u,a,f;for(;;){r=e.length,a=!1;for(o=n;o<r;o++){i=e[o];for(u=o+1;u<r;u++){f=i+e[u];if(!t[f]&&this._requires(i,e[u])){s=e.splice(u,1),e.splice(o,0,s[0]),t[f]=!0,a=!0;break}}if(a)break;n++}if(!a)break}this.sorted=e},_insert:function(t,n,r,i){t&&this._config(t);var s=this.resolve(!i),o=this,f=0,l=0,c={},h,p;o._refetch=[],r&&(s[r===a?u:a]=[]),o.fetchCSS||(s.css=[]),s.js.length&&f++,s.css.length&&f++,p=function(t){l++;var n={},r=0,i=0,s="",u,a,p;if(t&&t.errors)for(r=0;r<t.errors.length;r++)t.errors[r].request?s=t.errors[r].request.url:s=t.errors[r],n[s]=s;if(t&&t.data&&t.data.length&&t.type==="success")for(r=0;r<t.data.length;r++){o.inserted[t.data[r].name]=!0;if(t.data[r].lang||t.data[r].skinnable)delete o.inserted[t.data[r].name],o._refetch.push(t.data[r].name)}if(l===f){o._loading=null;if(o._refetch.length){for(r=0;r<o._refetch.length;r++){h=o.getRequires(o.getModule(o._refetch[r]));for(i=0;i<h.length;i++)o.inserted[h[i]]||(c[h[i]]=h[i])}c=e.Object.keys(c);if(c.length){o.require(c),p=o.resolve(!0);if(p.cssMods.length){for(r=0;r<p.cssMods.length;r++)a=p.cssMods[r].name,delete YUI.Env._cssLoaded[a],o.isCSSLoaded(a)&&(o.inserted[a]=!0,delete o.required[a]);o.sorted=[],o._sort()}t=null,o._insert()}}t&&t.fn&&(u=t.fn,delete t.fn,u.call(o,t))}},this._loading=!0;if(!s.js.length&&!s.css.length){l=-1,p({fn:o._onSuccess});return}s.css.length&&e.Get.css(s.css,{data:s.cssMods,attributes:o.cssAttributes,insertBefore:o.insertBefore,charset:o.charset,timeout:o.timeout,context:o,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}}),s.js.length&&e.Get.js(s.js,{data:s.jsMods,insertBefore:o.insertBefore,attributes:o.jsAttributes,charset:o.charset,timeout:o.timeout,autopurge:!1,context:o,async:o.async,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}})},_continue:function(){!m.running&&m.size()>0&&(m.running=!0,m.next()())},insert:function(t,n,r){var i=this,s=e.merge(this);delete s.require,delete s.dirty,m.add(function(){i._insert(s,t,n,r)}),this._continue()},loadNext:function(){return},_filter:function(e,t,n){var r=this.filter,i=t&&t in this.filters,s=i&&this.filters[t],o=n||(this.moduleInfo[t]?this.moduleInfo[t].group:null);return o&&this.groups[o]&&this.groups[o].filter&&(s=this.groups[o].filter,i=!0),e&&(i&&(r=b.isString(s)?this.FILTER_DEFS[s.toUpperCase()]||null:s),r&&(e=e.replace(new RegExp(r.searchExp,"g"),r.replaceStr))),e},_url:function(e,t,n){return this._filter((n||this.base||"")+e,t)},resolve:function(e,t){var r,s,o,f,c,h,p,d,v,m,g,y,w,E,S=[],x,T,N={},C=this,k,A,O=C.ignoreRegistered?{}:C.inserted,M={js:[],jsMods:[],css:[],cssMods:[]},_=C.loadType||"js",D;(C.skin.overrides||C.skin.defaultSkin!==l||C.ignoreRegistered)&&C._resetModules(),e&&C.calculate(),t=t||C.sorted,D=function(e){if(e){c=e.group&&C.groups[e.group]||n,c.async===!1&&(e.async=c.async),f=e.fullpath?C._filter(e.fullpath,t[s]):C._url(e.path,t[s],c.base||e.base);if(e.attributes||e.async===!1)f={url:f,async:e.async},e.attributes&&(f.attributes=e.attributes);M[e.type].push(f),M[e.type+"Mods"].push(e)}},r=t.length,y=C.comboBase,f=y,m={};for(s=0;s<r;s++){v=y,o=C.getModule(t[s]),h=o&&o.group,c=C.groups[h];if(h&&c){if(!c.combine||o.fullpath){D(o);continue}o.combine=!0,c.comboBase&&(v=c.comboBase),"root"in c&&b.isValue(c.root)&&(o.root=c.root),o.comboSep=c.comboSep||C.comboSep,o.maxURLLength=c.maxURLLength||C.maxURLLength}else if(!C.combine){D(o);continue}m[v]=m[v]||[],m[v].push(o)}for(p in m)if(m.hasOwnProperty(p)){N[p]=N[p]||{js:[],jsMods:[],css:[],cssMods:[]},f=p,g=m[p],r=g.length;if(r)for(s=0;s<r;s++){if(O[g[s]])continue;o=g[s],o&&(o.combine||!o.ext)?(N[p].comboSep=o.comboSep,N[p].group=o.group,N[p].maxURLLength=o.maxURLLength,d=(b.isValue(o.root)?o.root:C.root)+(o.path||o.fullpath),d=C._filter(d,o.name),N[p][o.type].push(d),N[p][o.type+"Mods"].push(o)):g[s]&&D(g[s])}}for(p in N){w=p,k=N[w].comboSep||C.comboSep,A=N[w].maxURLLength||C.maxURLLength;for(_ in N[w])if(_===a||_===u){E=N[w][_],g=N[w][_+"Mods"],r=E.length,x=w+E.join(k),T=x.length,A<=w.length&&(A=i);if(r)if(T>A){S=[];for(t=0;t<r;t++)S.push(E[t]),x=w+S.join(k),x.length>A&&(o=S.pop(),x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)),S=[],o&&S.push(o));S.length&&(x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)))}else M[_].push(C._filter(x,null,N[w].group));M[_+"Mods"]=M[_+"Mods"].concat(g)}}return N=null,M},load:function(e){if(!e)return;var t=this,n=t.resolve(!0);t.data=n,t.onEnd=function(){e.apply(t.context||t,arguments)},t.insert()}}},"3.7.3",{requires:["get","features"]}),YUI.add("loader-rollup",function(e,t){e.Loader.prototype._rollup=function(){var e,t,n,r,i=this.required,s,o=this.moduleInfo,u,a,f;if(this.dirty||!this.rollups){this.rollups={};for(e in o)o.hasOwnProperty(e)&&(n=this.getModule(e),n&&n.rollup&&(this.rollups[e]=n))}for(;;){u=!1;for(e in this.rollups)if(this.rollups.hasOwnProperty(e)&&!i[e]&&(!this.loaded[e]||this.forceMap[e])){n=this.getModule(e),r=n.supersedes||[],s=!1;if(!n.rollup)continue;a=0;for(t=0;t<r.length;t++){f=o[r[t]];if(this.loaded[r[t]]&&!this.forceMap[r[t]]){s=!1;break}if(i[r[t]]&&n.type===f.type){a++,s=a>=n.rollup;if(s)break}}s&&(i[e]=!0,u=!0,this.getRequires(n))}if(!u)break}}},"3.7.3",{requires:["loader-base"]}),YUI.add("loader-yui3",function(e,t){YUI.Env[e.version].modules=YUI.Env[e.version].modules||{"align-plugin":{requires:["node-screen","node-pluginhost"]},anim:{use:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"]},"anim-base":{requires:["base-base","node-style"]},"anim-color":{requires:["anim-base"]},"anim-curve":{requires:["anim-xy"]},"anim-easing":{requires:["anim-base"]},"anim-node-plugin":{requires:["node-pluginhost","anim-base"]},"anim-scroll":{requires:["anim-base"]},"anim-shape":{requires:["anim-base","anim-easing","anim-color","matrix"]},"anim-shape-transform":{use:["anim-shape"]},"anim-xy":{requires:["anim-base","node-screen"]},app:{use:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"]},"app-base":{requires:["classnamemanager","pjax-base","router","view"]},"app-content":{requires:["app-base","pjax-content"]},"app-transitions":{requires:["app-base"]},"app-transitions-css":{type:"css"},"app-transitions-native":{condition:{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"},requires:["app-transitions","app-transitions-css","parallel","transition"]},"array-extras":{requires:["yui-base"]},"array-invoke":{requires:["yui-base"]},arraylist:{requires:["yui-base"]},"arraylist-add":{requires:["arraylist"]},"arraylist-filter":{requires:["arraylist"]},arraysort:{requires:["yui-base"]},"async-queue":{requires:["event-custom"]},attribute:{use:["attribute-base","attribute-complex"]},"attribute-base":{requires:["attribute-core","attribute-events","attribute-extras"]},"attribute-complex":{requires:["attribute-base"]},"attribute-core":{requires:["oop"]},"attribute-events":{requires:["event-custom"]},"attribute-extras":{requires:["oop"]},autocomplete:{use:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"]},"autocomplete-base":{optional:["autocomplete-sources"],requires:["array-extras","base-build","escape","event-valuechange","node-base"]},"autocomplete-filters":{requires:["array-extras","text-wordbreak"]},"autocomplete-filters-accentfold":{requires:["array-extras","text-accentfold","text-wordbreak"]},"autocomplete-highlighters":{requires:["array-extras","highlight-base"]},"autocomplete-highlighters-accentfold":{requires:["array-extras","highlight-accentfold"]},"autocomplete-list":{after:["autocomplete-sources"],lang:["en"],requires:["autocomplete-base","event-resize","node-screen","selector-css3","shim-plugin","widget","widget-position","widget-position-align"],skinnable:!0},"autocomplete-list-keys":{condition:{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"},requires:["autocomplete-list","base-build"]},"autocomplete-plugin":{requires:["autocomplete-list","node-pluginhost"]},"autocomplete-sources":{optional:["io-base","json-parse","jsonp","yql"],requires:["autocomplete-base"]},base:{use:["base-base","base-pluginhost","base-build"]},"base-base":{after:["attribute-complex"],requires:["base-core","attribute-base"]},"base-build":{requires:["base-base"]},"base-core":{requires:["attribute-core"]},"base-pluginhost":{requires:["base-base","pluginhost"]},button:{requires:["button-core","cssbutton","widget"]},"button-core":{requires:["attribute-core","classnamemanager","node-base"]},"button-group":{requires:["button-plugin","cssbutton","widget"]},"button-plugin":{requires:["button-core","cssbutton","node-pluginhost"]},cache:{use:["cache-base","cache-offline","cache-plugin"]},"cache-base":{requires:["base"]},"cache-offline":{requires:["cache-base","json"]},"cache-plugin":{requires:["plugin","cache-base"]},calendar:{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["calendar-base","calendarnavigator"],skinnable:!0},"calendar-base":{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["widget","substitute","datatype-date","datatype-date-math","cssgrids"],skinnable:!0},calendarnavigator:{requires:["plugin","classnamemanager","datatype-date","node","substitute"],skinnable:!0},charts:{requires:["charts-base"]},"charts-base":{requires:["dom","datatype-number","datatype-date","event-custom","event-mouseenter","event-touch","widget","widget-position","widget-stack","graphics"]},"charts-legend":{requires:["charts-base"]},classnamemanager:{requires:["yui-base"]},"clickable-rail":{requires:["slider-base"]},collection:{use:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"]},console:{lang:["en","es","ja"],requires:["yui-log","widget"],skinnable:!0},"console-filters":{requires:["plugin","console"],skinnable:!0},controller:{use:["router"]},cookie:{requires:["yui-base"]},"createlink-base":{requires:["editor-base"]},cssbase:{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},"cssbase-context":{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},cssbutton:{type:"css"},cssfonts:{type:"css"},"cssfonts-context":{type:"css"},cssgrids:{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-base":{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-units":{optional:["cssreset","cssfonts"],requires:["cssgrids-base"],type:"css"},cssreset:{type:"css"},"cssreset-context":{type:"css"},dataschema:{use:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"]},"dataschema-array":{requires:["dataschema-base"]},"dataschema-base":{requires:["base"]},"dataschema-json":{requires:["dataschema-base","json"]},"dataschema-text":{requires:["dataschema-base"]},"dataschema-xml":{requires:["dataschema-base"]},datasource:{use:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"]},"datasource-arrayschema":{requires:["datasource-local","plugin","dataschema-array"]},"datasource-cache":{requires:["datasource-local","plugin","cache-base"]},"datasource-function":{requires:["datasource-local"]},"datasource-get":{requires:["datasource-local","get"]},"datasource-io":{requires:["datasource-local","io-base"]},"datasource-jsonschema":{requires:["datasource-local","plugin","dataschema-json"]},"datasource-local":{requires:["base"]},"datasource-polling":{requires:["datasource-local"]},"datasource-textschema":{requires:["datasource-local","plugin","dataschema-text"]},"datasource-xmlschema":{requires:["datasource-local","plugin","datatype-xml","dataschema-xml"]},datatable:{use:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"]},"datatable-base":{requires:["datatable-core","datatable-table","datatable-head","datatable-body","base-build","widget"],skinnable:!0},"datatable-base-deprecated":{requires:["recordset-base","widget","substitute","event-mouseenter"],skinnable:!0},"datatable-body":{requires:["datatable-core","view","classnamemanager"]},"datatable-column-widths":{requires:["datatable-base"]},"datatable-core":{requires:["escape","model-list","node-event-delegate"]},"datatable-datasource":{requires:["datatable-base","plugin","datasource-local"]},"datatable-datasource-deprecated":{requires:["datatable-base-deprecated","plugin","datasource-local"]},"datatable-deprecated":{use:["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"]},"datatable-head":{requires:["datatable-core","view","classnamemanager"]},"datatable-message":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-mutable":{requires:["datatable-base"]},"datatable-scroll":{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0},"datatable-scroll-deprecated":{requires:["datatable-base-deprecated","plugin"]},"datatable-sort":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-sort-deprecated":{lang:["en"],requires:["datatable-base-deprecated","plugin","recordset-sort"]},"datatable-table":{requires:["datatable-core","datatable-head","datatable-body","view","classnamemanager"]},datatype:{use:["datatype-date","datatype-number","datatype-xml"]},"datatype-date":{use:["datatype-date-parse","datatype-date-format","datatype-date-math"]},"datatype-date-format":{lang:["ar","ar-JO","ca","ca-ES","da","da-DK","de","de-AT","de-DE","el","el-GR","en","en-AU","en-CA","en-GB","en-IE","en-IN","en-JO","en-MY","en-NZ","en-PH","en-SG","en-US","es","es-AR","es-BO","es-CL","es-CO","es-EC","es-ES","es-MX","es-PE","es-PY","es-US","es-UY","es-VE","fi","fi-FI","fr","fr-BE","fr-CA","fr-FR","hi","hi-IN","id","id-ID","it","it-IT","ja","ja-JP","ko","ko-KR","ms","ms-MY","nb","nb-NO","nl","nl-BE","nl-NL","pl","pl-PL","pt","pt-BR","ro","ro-RO","ru","ru-RU","sv","sv-SE","th","th-TH","tr","tr-TR","vi","vi-VN","zh-Hans","zh-Hans-CN","zh-Hant","zh-Hant-HK","zh-Hant-TW"]},"datatype-date-math":{requires:["yui-base"]},"datatype-date-parse":{},"datatype-number":{use:["datatype-number-parse","datatype-number-format"]},"datatype-number-format":{},"datatype-number-parse":{},"datatype-xml":{use:["datatype-xml-parse","datatype-xml-format"]},"datatype-xml-format":{},"datatype-xml-parse":{},dd:{use:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"]},"dd-constrain":{requires:["dd-drag"]},"dd-ddm":{requires:["dd-ddm-base","event-resize"]},"dd-ddm-base":{requires:["node","base","yui-throttle","classnamemanager"]},"dd-ddm-drop":{requires:["dd-ddm"]},"dd-delegate":{requires:["dd-drag","dd-drop-plugin","event-mouseenter"]},"dd-drag":{requires:["dd-ddm-base"]},"dd-drop":{requires:["dd-drag","dd-ddm-drop"]},"dd-drop-plugin":{requires:["dd-drop"]},"dd-gestures":{condition:{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"},requires:["dd-drag","event-synthetic","event-gestures"]},"dd-plugin":{optional:["dd-constrain","dd-proxy"],requires:["dd-drag"]},"dd-proxy":{requires:["dd-drag"]},"dd-scroll":{requires:["dd-drag"]},dial:{lang:["en","es"],requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],skinnable:!0},dom:{use:["dom-base","dom-screen","dom-style","selector-native","selector"]},"dom-base":{requires:["dom-core"]},"dom-core":{requires:["oop","features"]},"dom-deprecated":{requires:["dom-base"]},"dom-screen":{requires:["dom-base","dom-style"]},"dom-style":{requires:["dom-base"]},"dom-style-ie":{condition:{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"},requires:["dom-style"]},dump:{requires:["yui-base"]},editor:{use:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"]},"editor-base":{requires:["base","frame","node","exec-command","editor-selection"]},"editor-bidi":{requires:["editor-base"]},"editor-br":{requires:["editor-base"]},"editor-lists":{requires:["editor-base"]},"editor-para":{requires:["editor-para-base"]},"editor-para-base":{requires:["editor-base"]},"editor-para-ie":{condition:{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"},requires:["editor-para-base"]},"editor-selection":{requires:["node"]},"editor-tab":{requires:["editor-base"]},escape:{requires:["yui-base"]},event:{after:["node-base"],use:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"]},"event-base":{after:["node-base"],requires:["event-custom-base"]},"event-base-ie":{after:["event-base"],condition:{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"},requires:["node-base"]},"event-contextmenu":{requires:["event-synthetic","dom-screen"]},"event-custom":{use:["event-custom-base","event-custom-complex"]},"event-custom-base":{requires:["oop"]},"event-custom-complex":{requires:["event-custom-base"]},"event-delegate":{requires:["node-base"]},"event-flick":{requires:["node-base","event-touch","event-synthetic"]},"event-focus":{requires:["event-synthetic"]},"event-gestures":{use:["event-flick","event-move"]},"event-hover":{requires:["event-mouseenter"]},"event-key":{requires:["event-synthetic"]},"event-mouseenter":{requires:["event-synthetic"]},"event-mousewheel":{requires:["node-base"]},"event-move":{requires:["node-base","event-touch","event-synthetic"]},"event-outside":{requires:["event-synthetic"]},"event-resize":{requires:["node-base","event-synthetic"]},"event-simulate":{requires:["event-base"]},"event-synthetic":{requires:["node-base","event-custom-complex"]},"event-tap":{requires:["node-base","event-base","event-touch","event-synthetic"]},"event-touch":{requires:["node-base"]},"event-valuechange":{requires:["event-focus","event-synthetic"]},"exec-command":{requires:["frame"]},features:{requires:["yui-base"]},file:{requires:["file-flash","file-html5"]},"file-flash":{requires:["base"]},"file-html5":{requires:["base"]},frame:{requires:["base","node","selector-css3","yui-throttle"]},"gesture-simulate":{requires:["async-queue","event-simulate","node-screen"]},get:{requires:["yui-base"]},graphics:{requires:["node","event-custom","pluginhost","matrix","classnamemanager"]},"graphics-canvas":{condition:{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"},requires:["graphics"]},"graphics-canvas-default":{condition:{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}},"graphics-svg":{condition:{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"},requires:["graphics"]},"graphics-svg-default":{condition:{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}},"graphics-vml":{condition:{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"},requires:["graphics"]},"graphics-vml-default":{condition:{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}},handlebars:{use:["handlebars-compiler"]},"handlebars-base":{requires:["escape"]},"handlebars-compiler":{requires:["handlebars-base"]},highlight:{use:["highlight-base","highlight-accentfold"]},"highlight-accentfold":{requires:["highlight-base","text-accentfold"]},"highlight-base":{requires:["array-extras","classnamemanager","escape","text-wordbreak"]},history:{use:["history-base","history-hash","history-hash-ie","history-html5"]},"history-base":{requires:["event-custom-complex"]},"history-hash":{after:["history-html5"],requires:["event-synthetic","history-base","yui-later"]},"history-hash-ie":{condition:{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"},requires:["history-hash","node-base"]},"history-html5":{optional:["json"],requires:["event-base","history-base","node-base"]},imageloader:{requires:["base-base","node-style","node-screen"]},intl:{requires:["intl-base","event-custom"]},"intl-base":{requires:["yui-base"]},io:{use:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"]},"io-base":{requires:["event-custom-base","querystring-stringify-simple"]},"io-form":{requires:["io-base","node-base"]},"io-nodejs":{condition:{name:"io-nodejs",trigger:"io-base",ua:"nodejs"},requires:["io-base"]},"io-queue":{requires:["io-base","queue-promote"]},"io-upload-iframe":{requires:["io-base","node-base"]},"io-xdr":{requires:["io-base","datatype-xml-parse"]},json:{use:["json-parse","json-stringify"]},"json-parse":{requires:["yui-base"]},"json-stringify":{requires:["yui-base"]},jsonp:{requires:["get","oop"]},"jsonp-url":{requires:["jsonp"]},"lazy-model-list":{requires:["model-list"]},loader:{use:["loader-base","loader-rollup","loader-yui3"]},"loader-base":{requires:["get","features"]},"loader-rollup":{requires:["loader-base"]},"loader-yui3":{requires:["loader-base"]},matrix:{requires:["yui-base"]},model:{requires:["base-build","escape","json-parse"]},"model-list":{requires:["array-extras","array-invoke","arraylist","base-build","escape","json-parse","model"]},"model-sync-rest":{requires:["model","io-base","json-stringify"]},node:{use:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"]},"node-base":{requires:["event-base","node-core","dom-base"]},"node-core":{requires:["dom-core","selector"]},"node-deprecated":{requires:["node-base"]},"node-event-delegate":{requires:["node-base","event-delegate"]},"node-event-html5":{requires:["node-base"]},"node-event-simulate":{requires:["node-base","event-simulate","gesture-simulate"]},"node-flick":{requires:["classnamemanager","transition","event-flick","plugin"],skinnable:!0},"node-focusmanager":{requires:["attribute","node","plugin","node-event-simulate","event-key","event-focus"]},"node-load":{requires:["node-base","io-base"]},"node-menunav":{requires:["node","classnamemanager","plugin","node-focusmanager"],skinnable:!0},"node-pluginhost":{requires:["node-base","pluginhost"]},"node-screen":{requires:["dom-screen","node-base"]},"node-scroll-info":{requires:["base-build","dom-screen","event-resize","node-pluginhost","plugin"]},"node-style":{requires:["dom-style","node-base"]},oop:{requires:["yui-base"]},overlay:{requires:["widget","widget-stdmod","widget-position","widget-position-align","widget-stack","widget-position-constrain"],skinnable:!0},panel:{requires:["widget","widget-autohide","widget-buttons","widget-modality","widget-position","widget-position-align","widget-position-constrain","widget-stack","widget-stdmod"],skinnable:!0},parallel:{requires:["yui-base"]},pjax:{requires:["pjax-base","pjax-content"]},"pjax-base":{requires:["classnamemanager","node-event-delegate","router"]},"pjax-content":{requires:["io-base","node-base","router"]},"pjax-plugin":{requires:["node-pluginhost","pjax","plugin"]},plugin:{requires:["base-base"]},pluginhost:{use:["pluginhost-base","pluginhost-config"]},"pluginhost-base":{requires:["yui-base"]},"pluginhost-config":{requires:["pluginhost-base"]},profiler:{requires:["yui-base"]},querystring:{use:["querystring-parse","querystring-stringify"]},"querystring-parse":{requires:["yui-base","array-extras"]},"querystring-parse-simple":{requires:["yui-base"]},"querystring-stringify":{requires:["yui-base"]},"querystring-stringify-simple":{requires:["yui-base"]},"queue-promote":{requires:["yui-base"]},"range-slider":{requires:["slider-base","slider-value-range","clickable-rail"]},recordset:{use:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"]},"recordset-base":{requires:["base","arraylist"]},"recordset-filter":{requires:["recordset-base","array-extras","plugin"]},"recordset-indexer":{requires:["recordset-base","plugin"]},"recordset-sort":{requires:["arraysort","recordset-base","plugin"]},resize:{use:["resize-base","resize-proxy","resize-constrain"]},"resize-base":{requires:["base","widget","event","oop","dd-drag","dd-delegate","dd-drop"],skinnable:!0},"resize-constrain":{requires:["plugin","resize-base"]},"resize-plugin":{optional:["resize-constrain"],requires:["resize-base","plugin"]},"resize-proxy":{requires:["plugin","resize-base"]},router:{optional:["querystring-parse"],requires:["array-extras","base-build","history"]},scrollview:{requires:["scrollview-base","scrollview-scrollbars"]},"scrollview-base":{requires:["widget","event-gestures","event-mousewheel","transition"],skinnable:!0},"scrollview-base-ie":{condition:{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"},requires:["scrollview-base"]},"scrollview-list":{requires:["plugin","classnamemanager"],skinnable:!0},"scrollview-paginator":{requires:["plugin","classnamemanager"]},"scrollview-scrollbars":{requires:["classnamemanager","transition","plugin"],skinnable:!0},selector:{requires:["selector-native"]},"selector-css2":{condition:{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"},requires:["selector-native"]},"selector-css3":{requires:["selector-native","selector-css2"]},"selector-native":{requires:["dom-base"]},"shim-plugin":{requires:["node-style","node-pluginhost"]},slider:{use:["slider-base","slider-value-range","clickable-rail","range-slider"]},"slider-base":{requires:["widget","dd-constrain","event-key"],skinnable:!0},"slider-value-range":{requires:["slider-base"]},sortable:{requires:["dd-delegate","dd-drop-plugin","dd-proxy"]},"sortable-scroll":{requires:["dd-scroll","sortable"]},stylesheet:{requires:["yui-base"]},substitute:{optional:["dump"],requires:["yui-base"]},swf:{requires:["event-custom","node","swfdetect","escape"]},swfdetect:{requires:["yui-base"]},tabview:{requires:["widget","widget-parent","widget-child","tabview-base","node-pluginhost","node-focusmanager"],skinnable:!0},"tabview-base":{requires:["node-event-delegate","classnamemanager","skin-sam-tabview"]},"tabview-plugin":{requires:["tabview-base"]},test:{requires:["event-simulate","event-custom","json-stringify"]},"test-console":{requires:["console-filters","test","array-extras"],skinnable:!0},text:{use:["text-accentfold","text-wordbreak"]},"text-accentfold":{requires:["array-extras","text-data-accentfold"]},"text-data-accentfold":{requires:["yui-base"]},"text-data-wordbreak":{requires:["yui-base"]},"text-wordbreak":{requires:["array-extras","text-data-wordbreak"]},transition:{requires:["node-style"]},"transition-timer":{condition:{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"},requires:["transition"]},uploader:{requires:["uploader-html5","uploader-flash"]},"uploader-deprecated":{requires:["event-custom","node","base","swf"]},"uploader-flash":{requires:["swf","widget","substitute","base","cssbutton","node","event-custom","file-flash","uploader-queue"]},"uploader-html5":{requires:["widget","node-event-simulate","substitute","file-html5","uploader-queue"]},"uploader-queue":{requires:["base"]},view:{requires:["base-build","node-event-delegate"]},"view-node-map":{requires:["view"]},widget:{use:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]},"widget-anim":{requires:["anim-base","plugin","widget"]},"widget-autohide":{requires:["base-build","event-key","event-outside","widget"]},"widget-base":{requires:["attribute","base-base","base-pluginhost","classnamemanager","event-focus","node-base","node-style"],skinnable:!0},"widget-base-ie":{condition:{name:"widget-base-ie",trigger:"widget-base",ua:"ie"},requires:["widget-base"]},"widget-buttons":{requires:["button-plugin","cssbutton","widget-stdmod"]},"widget-child":{requires:["base-build","widget"]},"widget-htmlparser":{requires:["widget-base"]},"widget-locale":{requires:["widget-base"]},"widget-modality":{requires:["base-build","event-outside","widget"],skinnable:!0},"widget-parent":{requires:["arraylist","base-build","widget"]},"widget-position":{requires:["base-build","node-screen","widget"]},"widget-position-align":{requires:["widget-position"]},"widget-position-constrain":{requires:["widget-position"]},"widget-skin":{requires:["widget-base"]},"widget-stack":{requires:["base-build","widget"],skinnable:!0},"widget-stdmod":{requires:["base-build","widget"]},"widget-uievents":{requires:["node-event-delegate","widget-base"]},yql:{requires:["jsonp","jsonp-url"]},"yql-nodejs":{condition:{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}},"yql-winjs":{condition:{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"}},yui:{},"yui-base":{},"yui-later":{requires:["yui-base"]},"yui-log":{requires:["yui-base"]},"yui-throttle":{requires:["yui-base"]}},YUI.Env[e.version].md5="a28e022ad022130f7a4fb4ac77a2f1df"},"3.7.3",{requires:["loader-base"]}),YUI.add("yui",function(e,t){},"3.7.3",{use:["get","features","intl-base","yui-log","yui-log-nodejs","yui-later","loader-base","loader-rollup","loader-yui3"]});
diff --git a/js/yui3/yui-throttle/yui-throttle-min.js b/js/yui3/yui-throttle/yui-throttle-min.js
new file mode 100644
index 000000000..0b8429e86
--- /dev/null
+++ b/js/yui3/yui-throttle/yui-throttle-min.js
@@ -0,0 +1,9 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+YUI.add("yui-throttle",function(e,t){
+/*! Based on work by Simon Willison: http://gist.github.com/292562 */
+;e.throttle=function(t,n){n=n?n:e.config.throttleTime||150;if(n===-1)return function(){t.apply(null,arguments)};var r=e.Lang.now();return function(){var i=e.Lang.now();i-r>n&&(r=i,t.apply(null,arguments))}}},"3.7.3",{requires:["yui-base"]});
diff --git a/js/yui3/yui/yui-min.js b/js/yui3/yui/yui-min.js
new file mode 100644
index 000000000..0dd31f8c8
--- /dev/null
+++ b/js/yui3/yui/yui-min.js
@@ -0,0 +1,7 @@
+/*
+YUI 3.7.3 (build 5687)
+Copyright 2012 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+typeof YUI!="undefined"&&(YUI._YUI=YUI);var YUI=function(){var e=0,t=this,n=arguments,r=n.length,i=function(e,t){return e&&e.hasOwnProperty&&e instanceof t},s=typeof YUI_config!="undefined"&&YUI_config;i(t,YUI)?(t._init(),YUI.GlobalConfig&&t.applyConfig(YUI.GlobalConfig),s&&t.applyConfig(s),r||t._setup()):t=new YUI;if(r){for(;e<r;e++)t.applyConfig(n[e]);t._setup()}return t.instanceOf=i,t};(function(){var e,t,n="3.7.3",r=".",i="http://yui.yahooapis.com/",s="yui3-js-enabled",o="yui3-css-stamp",u=function(){},a=Array.prototype.slice,f={"io.xdrReady":1,"io.xdrResponse":1,"SWF.eventHandler":1},l=typeof window!="undefined",c=l?window:null,h=l?c.document:null,p=h&&h.documentElement,d=p&&p.className,v={},m=(new Date).getTime(),g=function(e,t,n,r){e&&e.addEventListener?e.addEventListener(t,n,r):e&&e.attachEvent&&e.attachEvent("on"+t,n)},y=function(e,t,n,r){if(e&&e.removeEventListener)try{e.removeEventListener(t,n,r)}catch(i){}else e&&e.detachEvent&&e.detachEvent("on"+t,n)},b=function(){YUI.Env.windowLoaded=!0,YUI.Env.DOMReady=!0,l&&y(window,"load",b)},w=function(e,t){var n=e.Env._loader,r=["loader-base"],i=YUI.Env,s=i.mods;return n?(n.ignoreRegistered=!1,n.onEnd=null,n.data=null,n.required=[],n.loadType=null):(n=new e.Loader(e.config),e.Env._loader=n),s&&s.loader&&(r=[].concat(r,YUI.Env.loaderExtras)),YUI.Env.core=e.Array.dedupe([].concat(YUI.Env.core,r)),n},E=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},S={success:!0};p&&d.indexOf(s)==-1&&(d&&(d+=" "),d+=s,p.className=d),n.indexOf("@")>-1&&(n="3.5.0"),e={applyConfig:function(e){e=e||u;var t,n,r=this.config,i=r.modules,s=r.groups,o=r.aliases,a=this.Env._loader;for(n in e)e.hasOwnProperty(n)&&(t=e[n],i&&n=="modules"?E(i,t):o&&n=="aliases"?E(o,t):s&&n=="groups"?E(s,t):n=="win"?(r[n]=t&&t.contentWindow||t,r.doc=r[n]?r[n].document:null):n!="_yuid"&&(r[n]=t));a&&a._config(e)},_config:function(e){this.applyConfig(e)},_init:function(){var e,t,r=this,s=YUI.Env,u=r.Env,a;r.version=n;if(!u){r.Env={core:["get","features","intl-base","yui-log","yui-later","loader-base","loader-rollup","loader-yui3"],loaderExtras:["loader-rollup","loader-yui3"],mods:{},versions:{},base:i,cdn:i+n+"/build/",_idx:0,_used:{},_attached:{},_missed:[],_yidx:0,_uidx:0,_guidp:"y",_loaded:{},_BASE_RE:/(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,parseBasePath:function(e,t){var n=e.match(t),r,i;return n&&(r=RegExp.leftContext||e.slice(0,e.indexOf(n[0])),i=n[3],n[1]&&(r+="?"+n[1]),r={filter:i,path:r}),r},getBase:s&&s.getBase||function(t){var n=h&&h.getElementsByTagName("script")||[],i=u.cdn,s,o,a,f;for(o=0,a=n.length;o<a;++o){f=n[o].src;if(f){s=r.Env.parseBasePath(f,t);if(s){e=s.filter,i=s.path;break}}}return i}},u=r.Env,u._loaded[n]={};if(s&&r!==YUI)u._yidx=++s._yidx,u._guidp=("yui_"+n+"_"+u._yidx+"_"+m).replace(/\./g,"_").replace(/-/g,"_");else if(YUI._YUI){s=YUI._YUI.Env,u._yidx+=s._yidx,u._uidx+=s._uidx;for(a in s)a in u||(u[a]=s[a]);delete YUI._YUI}r.id=r.stamp(r),v[r.id]=r}r.constructor=YUI,r.config=r.config||{bootstrap:!0,cacheUse:!0,debug:!0,doc:h,fetchCSS:!0,throwFail:!0,useBrowserConsole:!0,useNativeES5:!0,win:c},h&&!h.getElementById(o)&&(t=h.createElement("div"),t.innerHTML='<div id="'+o+'" style="position: absolute !important; visibility: hidden !important"></div>',YUI.Env.cssStampEl=t.firstChild,h.body?h.body.appendChild(YUI.Env.cssStampEl):p.insertBefore(YUI.Env.cssStampEl,p.firstChild)),r.config.lang=r.config.lang||"en-US",r.config.base=YUI.config.base||r.Env.getBase(r.Env._BASE_RE);if(!e||!"mindebug".indexOf(e))e="min";e=e?"-"+e:e,r.config.loaderPath=YUI.config.loaderPath||"loader/loader"+e+".js"},_setup:function(e){var t,n=this,r=[],i=YUI.Env.mods,s=n.config.core||[].concat(YUI.Env.core);for(t=0;t<s.length;t++)i[s[t]]&&r.push(s[t]);n._attach(["yui-base"]),n._attach(r),n.Loader&&w(n)},applyTo:function(e,t,n){if(t in f){var r=v[e],i,s,o;if(r){i=t.split("."),s=r;for(o=0;o<i.length;o+=1)s=s[i[o]],s||this.log("applyTo not found: "+t,"warn","yui");return s&&s.apply(r,n)}return null}return this.log(t+": applyTo not allowed","warn","yui"),null},add:function(e,t,n,r){r=r||{};var i=YUI.Env,s={name:e,fn:t,version:n,details:r},o={},u,a,f,l=i.versions;i.mods[e]=s,l[n]=l[n]||{},l[n][e]=s;for(f in v)v.hasOwnProperty(f)&&(a=v[f],o[a.id]||(o[a.id]=!0,u=a.Env._loader,u&&(!u.moduleInfo[e]||u.moduleInfo[e].temp)&&u.addModule(r,e)));return this},_attach:function(e,t){var n,r,i,s,o,u,a,f=YUI.Env.mods,l=YUI.Env.aliases,c=this,h,p=YUI.Env._renderedMods,d=c.Env._loader,v=c.Env._attached,m=e.length,d,g,y,b=[];for(n=0;n<m;n++){r=e[n],i=f[r],b.push(r);if(d&&d.conditions[r])for(h in d.conditions[r])d.conditions[r].hasOwnProperty(h)&&(g=d.conditions[r][h],y=g&&(g.ua&&c.UA[g.ua]||g.test&&g.test(c)),y&&b.push(g.name))}e=b,m=e.length;for(n=0;n<m;n++)if(!v[e[n]]){r=e[n],i=f[r];if(l&&l[r]&&!i){c._attach(l[r]);continue}if(!i)d&&d.moduleInfo[r]&&(i=d.moduleInfo[r],t=!0),!t&&r&&r.indexOf("skin-")===-1&&r.indexOf("css")===-1&&(c.Env._missed.push(r),c.Env._missed=c.Array.dedupe(c.Env._missed),c.message("NOT loaded: "+r,"warn","yui"));else{v[r]=!0;for(h=0;h<c.Env._missed.length;h++)c.Env._missed[h]===r&&(c.message("Found: "+r+" (was reported as missing earlier)","warn","yui"),c.Env._missed.splice(h,1));if(d&&p&&p[r]&&p[r].temp){d.getRequires(p[r]),o=[];for(h in d.moduleInfo[r].expanded_map)d.moduleInfo[r].expanded_map.hasOwnProperty(h)&&o.push(h);c._attach(o)}s=i.details,o=s.requires,u=s.use,a=s.after,s.lang&&(o=o||[],o.unshift("intl"));if(o)for(h=0;h<o.length;h++)if(!v[o[h]]){if(!c._attach(o))return!1;break}if(a)for(h=0;h<a.length;h++)if(!v[a[h]]){if(!c._attach(a,!0))return!1;break}if(i.fn)if(c.config.throwFail)i.fn(c,r);else try{i.fn(c,r)}catch(w){return c.error("Attach error: "+r,w,r),!1}if(u)for(h=0;h<u.length;h++)if(!v[u[h]]){if(!c._attach(u))return!1;break}}}return!0},_delayCallback:function(e,t){var n=this,r=["event-base"];return t=n.Lang.isObject(t)?t:{event:t},t.event==="load"&&r.push("event-synthetic"),function(){var i=arguments;n._use(r,function(){n.on(t.event,function(){i[1].delayUntil=t.event,e.apply(n,i)},t.args)})}},use:function(){var e=a.call(arguments,0),t=e[e.length-1],n=this,r=0,i=[],s,o=n.Env,u=!0;n.Lang.isFunction(t)?(e.pop(),n.config.delayUntil&&(t=n._delayCallback(t,n.config.delayUntil))):t=null,n.Lang.isArray(e[0])&&(e=e[0]);if(n.config.cacheUse){while(s=e[r++])if(!o._attached[s]){u=!1;break}if(u)return e.length,n._notify(t,S,e),n}return n._loading?(n._useQueue=n._useQueue||new n.Queue,n._useQueue.add([e,t])):n._use(e,function(n,r){n._notify(t,r,e)}),n},_notify:function(e,t,n){if(!t.success&&this.config.loadErrorFn)this.config.loadErrorFn.call(this,this,e,t,n);else if(e){this.Env._missed&&this.Env._missed.length&&(t.msg="Missing modules: "+this.Env._missed.join(),t.success=!1);if(this.config.throwFail)e(this,t);else try{e(this,t)}catch(r){this.error("use callback error",r,n)}}},_use:function(e,t){this.Array||this._attach(["yui-base"]);var r,i,s,o,u=this,a=YUI.Env,f=a.mods,l=u.Env,c=l._used,h=a.aliases,p=a._loaderQueue,d=e[0],v=u.Array,m=u.config,g=m.bootstrap,y=[],b,E=[],S=!0,x=m.fetchCSS,T=function(e,t){var r=0,i=[],s,o,u,l,p;if(!e.length)return;if(h){o=e.length;for(r=0;r<o;r++)h[e[r]]&&!f[e[r]]?i=[].concat(i,h[e[r]]):i.push(e[r]);e=i}o=e.length;for(r=0;r<o;r++){s=e[r],t||E.push(s);if(c[s])continue;u=f[s],l=null,p=null,u?(c[s]=!0,l=u.details.requires,p=u.details.use):a._loaded[n][s]?c[s]=!0:y.push(s),l&&l.length&&T(l),p&&p.length&&T(p,1)}},N=function(n){var r=n||{success:!0,msg:"not dynamic"},i,s,o=!0,a=r.data;u._loading=!1,a&&(s=y,y=[],E=[],T(a),i=y.length,i&&[].concat(y).sort().join()==s.sort().join()&&(i=!1)),i&&a?(u._loading=!0,u._use(y,function(){u._attach(a)&&u._notify(t,r,a)})):(a&&(o=u._attach(a)),o&&u._notify(t,r,e)),u._useQueue&&u._useQueue.size()&&!u._loading&&u._use.apply(u,u._useQueue.next())};if(d==="*"){e=[];for(b in f)f.hasOwnProperty(b)&&e.push(b);return S=u._attach(e),S&&N(),u}return(f.loader||f["loader-base"])&&!u.Loader&&u._attach(["loader"+(f.loader?"":"-base")]),g&&u.Loader&&e.length&&(i=w(u),i.require(e),i.ignoreRegistered=!0,i._boot=!0,i.calculate(null,x?null:"js"),e=i.sorted,i._boot=!1),T(e),r=y.length,r&&(y=v.dedupe(y),r=y.length),g&&r&&u.Loader?(u._loading=!0,i=w(u),i.onEnd=N,i.context=u,i.data=e,i.ignoreRegistered=!1,i.require(e),i.insert(null,x?null:"js")):g&&r&&u.Get&&!l.bootstrapped?(u._loading=!0,s=function(){u._loading=!1,p.running=!1,l.bootstrapped=!0,a._bootstrapping=!1,u._attach(["loader"])&&u._use(e,t)},a._bootstrapping?p.add(s):(a._bootstrapping=!0,u.Get.script(m.base+m.loaderPath,{onEnd:s}))):(S=u._attach(e),S&&N()),u},namespace:function(){var e=arguments,t,n=0,i,s,o;for(;n<e.length;n++){t=this,o=e[n];if(o.indexOf(r)>-1){s=o.split(r);for(i=s[0]=="YAHOO"?1:0;i<s.length;i++)t[s[i]]=t[s[i]]||{},t=t[s[i]]}else t[o]=t[o]||{},t=t[o]}return t},log:u,message:u,dump:function(e){return""+e},error:function(e,t,n){var r=this,i;r.config.errorFn&&(i=r.config.errorFn.apply(r,arguments));if(!i)throw t||new Error(e);return r.message(e,"error",""+n),r},guid:function(e){var t=this.Env._guidp+"_"+ ++this.Env._uidx;return e?e+t:t},stamp:function(e,t){var n;if(!e)return e;e.uniqueID&&e.nodeType&&e.nodeType!==9?n=e.uniqueID:n=typeof e=="string"?e:e._yuid;if(!n){n=this.guid();if(!t)try{e._yuid=n}catch(r){n=null}}return n},destroy:function(){var e=this;e.Event&&e.Event._unload(),delete v[e.id],delete e.Env,delete e.config}},YUI.prototype=e;for(t in e)e.hasOwnProperty(t)&&(YUI[t]=e[t]);YUI.applyConfig=function(e){if(!e)return;YUI.GlobalConfig&&this.prototype.applyConfig.call(this,YUI.GlobalConfig),this.prototype.applyConfig.call(this,e),YUI.GlobalConfig=this.config},YUI._init(),l?g(window,"load",b):b(),YUI.Env.add=g,YUI.Env.remove=y,typeof exports=="object"&&(exports.YUI=YUI)})(),YUI.add("yui-base",function(e,t){function h(e,t,n){var r,i;t||(t=0);if(n||h.test(e))try{return l.slice.call(e,t)}catch(s){i=[];for(r=e.length;t<r;++t)i.push(e[t]);return i}return[e]}function p(){this._init(),this.add.apply(this,arguments)}var n=e.Lang||(e.Lang={}),r=String.prototype,i=Object.prototype.toString,s={"undefined":"undefined",number:"number","boolean":"boolean",string:"string","[object Function]":"function","[object RegExp]":"regexp","[object Array]":"array","[object Date]":"date","[object Error]":"error"},o=/\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,u=/^\s+|\s+$/g,a=/\{\s*\[(?:native code|function)\]\s*\}/i;n._isNative=function(t){return!!(e.config.useNativeES5&&t&&a.test(t))},n.isArray=n._isNative(Array.isArray)?Array.isArray:function(e){return n.type(e)==="array"},n.isBoolean=function(e){return typeof e=="boolean"},n.isDate=function(e){return n.type(e)==="date"&&e.toString()!=="Invalid Date"&&!isNaN(e)},n.isFunction=function(e){return n.type(e)==="function"},n.isNull=function(e){return e===null},n.isNumber=function(e){return typeof e=="number"&&isFinite(e)},n.isObject=function(e,t){var r=typeof e;return e&&(r==="object"||!t&&(r==="function"||n.isFunction(e)))||!1},n.isString=function(e){return typeof e=="string"},n.isUndefined=function(e){return typeof e=="undefined"},n.isValue=function(e){var t=n.type(e);switch(t){case"number":return isFinite(e);case"null":case"undefined":return!1;default:return!!t}},n.now=Date.now||function(){return(new Date).getTime()},n.sub=function(e,t){return e.replace?e.replace(o,function(e,r){return n.isUndefined(t[r])?e:t[r]}):e},n.trim=r.trim?function(e){return e&&e.trim?e.trim():e}:function(e){try{return e.replace(u,"")}catch(t){return e}},n.trimLeft=r.trimLeft?function(e){return e.trimLeft()}:function(e){return e.replace(/^\s+/,"")},n.trimRight=r.trimRight?function(e){return e.trimRight()}:function(e){return e.replace(/\s+$/,"")},n.type=function(e){return s[typeof e]||s[i.call(e)]||(e?"object":"null")};var f=e.Lang,l=Array.prototype,c=Object.prototype.hasOwnProperty;e.Array=h,h.dedupe=function(e){var t={},n=[],r,i,s;for(r=0,s=e.length;r<s;++r)i=e[r],c.call(t,i)||(t[i]=1,n.push(i));return n},h.each=h.forEach=f._isNative(l.forEach)?function(t,n,r){return l.forEach.call(t||[],n,r||e),e}:function(t,n,r){for(var i=0,s=t&&t.length||0;i<s;++i)i in t&&n.call(r||e,t[i],i,t);return e},h.hash=function(e,t){var n={},r=t&&t.length||0,i,s;for(i=0,s=e.length;i<s;++i)i in e&&(n[e[i]]=r>i&&i in t?t[i]:!0);return n},h.indexOf=f._isNative(l.indexOf)?function(e,t,n){return l.indexOf.call(e,t,n)}:function(e,t,n){var r=e.length;n=+n||0,n=(n>0||-1)*Math.floor(Math.abs(n)),n<0&&(n+=r,n<0&&(n=0));for(;n<r;++n)if(n in e&&e[n]===t)return n;return-1},h.numericSort=function(e,t){return e-t},h.some=f._isNative(l.some)?function(e,t,n){return l.some.call(e,t,n)}:function(e,t,n){for(var r=0,i=e.length;r<i;++r)if(r in e&&t.call(n,e[r],r,e))return!0;return!1},h.test=function(e){var t=0;if(f.isArray(e))t=1;else if(f.isObject(e))try{"length"in e&&!e.tagName&&(!e.scrollTo||!e.document)&&!e.apply&&(t=2)}catch(n){}return t},p.prototype={_init:function(){this._q=[]},next:function(){return this._q.shift()},last:function(){return this._q.pop()},add:function(){return this._q.push.apply(this._q,arguments),this},size:function(){return this._q.length}},e.Queue=p,YUI.Env._loaderQueue=YUI.Env._loaderQueue||new p;var d="__",c=Object.prototype.hasOwnProperty,v=e.Lang.isObject;e.cached=function(e,t,n){return t||(t={}),function(r){var i=arguments.length>1?Array.prototype.join.call(arguments,d):String(r);if(!(i in t)||n&&t[i]==n)t[i]=e.apply(e,arguments);return t[i]}},e.getLocation=function(){var t=e.config.win;return t&&t.location},e.merge=function(){var e=0,t=arguments.length,n={},r,i;for(;e<t;++e){i=arguments[e];for(r in i)c.call(i,r)&&(n[r]=i[r])}return n},e.mix=function(t,n,r,i,s,o){var u,a,f,l,h,p,d;if(!t||!n)return t||e;if(s){s===2&&e.mix(t.prototype,n.prototype,r,i,0,o),f=s===1||s===3?n.prototype:n,d=s===1||s===4?t.prototype:t;if(!f||!d)return t}else f=n,d=t;u=r&&!o;if(i)for(l=0,p=i.length;l<p;++l){h=i[l];if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}else{for(h in f){if(!c.call(f,h))continue;a=u?!1:h in d;if(o&&a&&v(d[h],!0)&&v(f[h],!0))e.mix(d[h],f[h],r,null,0,o);else if(r||!a)d[h]=f[h]}e.Object._hasEnumBug&&e.mix(d,f,r,e.Object._forceEnum,s,o)}return t};var f=e.Lang,c=Object.prototype.hasOwnProperty,m,g=e.Object=f._isNative(Object.create)?function(e){return Object.create(e)}:function(){function e(){}return function(t){return e.prototype=t,new e}}(),y=g._forceEnum=["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","toLocaleString","valueOf"],b=g._hasEnumBug=!{valueOf:0}.propertyIsEnumerable("valueOf"),w=g._hasProtoEnumBug=function(){}.propertyIsEnumerable("prototype"),E=g.owns=function(e,t){return!!e&&c.call(e,t)};g.hasKey=E,g.keys=f._isNative(Object.keys)?Object.keys:function(e){if(!f.isObject(e))throw new TypeError("Object.keys called on a non-object");var t=[],n,r,i;if(w&&typeof e=="function")for(r in e)E(e,r)&&r!=="prototype"&&t.push(r);else for(r in e)E(e,r)&&t.push(r);if(b)for(n=0,i=y.length;n<i;++n)r=y[n],E(e,r)&&t.push(r);return t},g.values=function(e){var t=g.keys(e),n=0,r=t.length,i=[];for(;n<r;++n)i.push(e[t[n]]);return i},g.size=function(e){try{return g.keys(e).length}catch(t){return 0}},g.hasValue=function(t,n){return e.Array.indexOf(g.values(t),n)>-1},g.each=function(t,n,r,i){var s;for(s in t)(i||E(t,s))&&n.call(r||e,t[s],s,t);return e},g.some=function(t,n,r,i){var s;for(s in t)if(i||E(t,s))if(n.call(r||e,t[s],s,t))return!0;return!1},g.getValue=function(t,n){if(!f.isObject(t))return m;var r,i=e.Array(n),s=i.length;for(r=0;t!==m&&r<s;r++)t=t[i[r]];return t},g.setValue=function(t,n,r){var i,s=e.Array(n),o=s.length-1,u=t;if(o>=0){for(i=0;u!==m&&i<o;i++)u=u[s[i]];if(u===m)return m;u[s[i]]=r}return t},g.isEmpty=function(e){return!g.keys(Object(e)).length},YUI.Env.parseUA=function(t){var n=function(e){var t=0;return parseFloat(e.replace(/\./g,function(){return t++===1?"":"."}))},r=e.config.win,i=r&&r.navigator,s={ie:0,opera:0,gecko:0,webkit:0,safari:0,chrome:0,mobile:null,air:0,phantomjs:0,ipad:0,iphone:0,ipod:0,ios:null,android:0,silk:0,accel:!1,webos:0,caja:i&&i.cajaVersion,secure:!1,os:null,nodejs:0,winjs:typeof Windows!="undefined"&&!!Windows.System,touchEnabled:!1},o=t||i&&i.userAgent,u=r&&r.location,a=u&&u.href,f;return s.userAgent=o,s.secure=a&&a.toLowerCase().indexOf("https")===0,o&&(/windows|win32/i.test(o)?s.os="windows":/macintosh|mac_powerpc/i.test(o)?s.os="macintosh":/android/i.test(o)?s.os="android":/symbos/i.test(o)?s.os="symbos":/linux/i.test(o)?s.os="linux":/rhino/i.test(o)&&(s.os="rhino"),/KHTML/.test(o)&&(s.webkit=1),/IEMobile|XBLWP7/.test(o)&&(s.mobile="windows"),/Fennec/.test(o)&&(s.mobile="gecko"),f=o.match(/AppleWebKit\/([^\s]*)/),f&&f[1]&&(s.webkit=n(f[1]),s.safari=s.webkit,/PhantomJS/.test(o)&&(f=o.match(/PhantomJS\/([^\s]*)/),f&&f[1]&&(s.phantomjs=n(f[1]))),/ Mobile\//.test(o)||/iPad|iPod|iPhone/.test(o)?(s.mobile="Apple",f=o.match(/OS ([^\s]*)/),f&&f[1]&&(f=n(f[1].replace("_","."))),s.ios=f,s.os="ios",s.ipad=s.ipod=s.iphone=0,f=o.match(/iPad|iPod|iPhone/),f&&f[0]&&(s[f[0].toLowerCase()]=s.ios)):(f=o.match(/NokiaN[^\/]*|webOS\/\d\.\d/),f&&(s.mobile=f[0]),/webOS/.test(o)&&(s.mobile="WebOS",f=o.match(/webOS\/([^\s]*);/),f&&f[1]&&(s.webos=n(f[1]))),/ Android/.test(o)&&(/Mobile/.test(o)&&(s.mobile="Android"),f=o.match(/Android ([^\s]*);/),f&&f[1]&&(s.android=n(f[1]))),/Silk/.test(o)&&(f=o.match(/Silk\/([^\s]*)\)/),f&&f[1]&&(s.silk=n(f[1])),s.android||(s.android=2.34,s.os="Android"),/Accelerated=true/.test(o)&&(s.accel=!0))),f=o.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/),f&&f[1]&&f[2]?(s.chrome=n(f[2]),s.safari=0,f[1]==="CrMo"&&(s.mobile="chrome")):(f=o.match(/AdobeAIR\/([^\s]*)/),f&&(s.air=f[0]))),s.webkit||(/Opera/.test(o)?(f=o.match(/Opera[\s\/]([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),f=o.match(/Version\/([^\s]*)/),f&&f[1]&&(s.opera=n(f[1])),/Opera Mobi/.test(o)&&(s.mobile="opera",f=o.replace("Opera Mobi","").match(/Opera ([^\s]*)/),f&&f[1]&&(s.opera=n(f[1]))),f=o.match(/Opera Mini[^;]*/),f&&(s.mobile=f[0])):(f=o.match(/MSIE\s([^;]*)/),f&&f[1]?s.ie=n(f[1]):(f=o.match(/Gecko\/([^\s]*)/),f&&(s.gecko=1,f=o.match(/rv:([^\s\)]*)/),f&&f[1]&&(s.gecko=n(f[1]))))))),r&&i&&!(s.chrome&&s.chrome<6)&&(s.touchEnabled="ontouchstart"in r||"msMaxTouchPoints"in i&&i.msMaxTouchPoints>0),t||(typeof process=="object"&&process.versions&&process.versions.node&&(s.os=process.platform,s.nodejs=n(process.versions.node)),YUI.Env.UA=s),s},e.UA=YUI.Env.UA||YUI.Env.parseUA(),e.UA.compareVersions=function(e,t){var n,r,i,s,o,u;if(e===t)return 0;r=(e+"").split("."),s=(t+"").split(".");for(o=0,u=Math.max(r.length,s.length);o<u;++o){n=parseInt(r[o],10),i=parseInt(s[o],10),isNaN(n)&&(n=0),isNaN(i)&&(i=0);if(n<i)return-1;if(n>i)return 1}return 0},YUI.Env.aliases={anim:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],"anim-shape-transform":["anim-shape"],app:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],attribute:["attribute-base","attribute-complex"],autocomplete:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],base:["base-base","base-pluginhost","base-build"],cache:["cache-base","cache-offline","cache-plugin"],collection:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],controller:["router"],dataschema:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],datasource:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],datatable:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],"datatable-deprecated":["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],datatype:["datatype-date","datatype-number","datatype-xml"],"datatype-date":["datatype-date-parse","datatype-date-format","datatype-date-math"],"datatype-number":["datatype-number-parse","datatype-number-format"],"datatype-xml":["datatype-xml-parse","datatype-xml-format"],dd:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],dom:["dom-base","dom-screen","dom-style","selector-native","selector"],editor:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],event:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],"event-custom":["event-custom-base","event-custom-complex"],"event-gestures":["event-flick","event-move"],handlebars:["handlebars-compiler"],highlight:["highlight-base","highlight-accentfold"],history:["history-base","history-hash","history-hash-ie","history-html5"],io:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],json:["json-parse","json-stringify"],loader:["loader-base","loader-rollup","loader-yui3"],node:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],pluginhost:["pluginhost-base","pluginhost-config"],querystring:["querystring-parse","querystring-stringify"],recordset:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],resize:["resize-base","resize-proxy","resize-constrain"],slider:["slider-base","slider-value-range","clickable-rail","range-slider"],text:["text-accentfold","text-wordbreak"],widget:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]}},"3.7.3",{use:["yui-base","get","features","intl-base","yui-log","yui-later","loader-base","loader-rollup","loader-yui3"]}),YUI.add("get",function(e,t){var n=e.Lang,r,i,s;e.Get=i={cssOptions:{attributes:{rel:"stylesheet"},doc:e.config.linkDoc||e.config.doc,pollInterval:50},jsOptions:{autopurge:!0,doc:e.config.scriptDoc||e.config.doc},options:{attributes:{charset:"utf-8"},purgethreshold:20},REGEX_CSS:/\.css(?:[?;].*)?$/i,REGEX_JS:/\.js(?:[?;].*)?$/i,_insertCache:{},_pending:null,_purgeNodes:[],_queue:[],abort:function(e){var t,n,r,i,s;if(!e.abort){n=e,s=this._pending,e=null;if(s&&s.transaction.id===n)e=s.transaction,this._pending=null;else for(t=0,i=this._queue.length;t<i;++t){r=this._queue[t].transaction;if(r.id===n){e=r,this._queue.splice(t,1);break}}}e&&e.abort()},css:function(e,t,n){return this._load("css",e,t,n)},js:function(e,t,n){return this._load("js",e,t,n)},load:function(e,t,n){return this._load(null,e,t,n)},_autoPurge:function(e){e&&this._purgeNodes.length>=e&&this._purge(this._purgeNodes)},_getEnv:function(){var t=e.config.doc,n=e.UA;return this._env={async:t&&t.createElement("script").async===!0||n.ie>=10,cssFail:n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0,cssLoad:(!n.gecko&&!n.webkit||n.gecko>=9||n.compareVersions(n.webkit,535.24)>=0)&&!(n.chrome&&n.chrome<=18),preservesScriptOrder:!!(n.gecko||n.opera||n.ie&&n.ie>=10)}},_getTransaction:function(t,r){var i=[],o,u,a,f;n.isArray(t)||(t=[t]),r=e.merge(this.options,r),r.attributes=e.merge(this.options.attributes,r.attributes);for(o=0,u=t.length;o<u;++o){f=t[o],a={attributes:{}};if(typeof f=="string")a.url=f;else{if(!f.url)continue;e.mix(a,f,!1,null,0,!0),f=f.url}e.mix(a,r,!1,null,0,!0),a.type||(this.REGEX_CSS.test(f)?a.type="css":(!this.REGEX_JS.test(f),a.type="js")),e.mix(a,a.type==="js"?this.jsOptions:this.cssOptions,!1,null,0,!0),a.attributes.id||(a.attributes.id=e.guid()),a.win?a.doc=a.win.document:a.win=a.doc.defaultView||a.doc.parentWindow,a.charset&&(a.attributes.charset=a.charset),i.push(a)}return new s(i,r)},_load:function(e,t,n,r){var s;return typeof n=="function"&&(r=n,n={}),n||(n={}),n.type=e,n._onFinish=i._onTransactionFinish,this._env||this._getEnv(),s=this._getTransaction(t,n),this._queue.push({callback:r,transaction:s}),this._next(),s},_onTransactionFinish:function(){i._pending=null,i._next()},_next:function(){var e;if(this._pending)return;e=this._queue.shift(),e&&(this._pending=e,e.transaction.execute(e.callback))},_purge:function(t){var n=this._purgeNodes,r=t!==n,i,s;while(s=t.pop()){if(!s._yuiget_finished)continue;s.parentNode&&s.parentNode.removeChild(s),r&&(i=e.Array.indexOf(n,s),i>-1&&n.splice(i,1))}}},i.script=i.js,i.Transaction=s=function(t,n){var r=this;r.id=s._lastId+=1,r.data=n.data,r.errors=[],r.nodes=[],r.options=n,r.requests=t,r._callbacks=[],r._queue=[],r._reqsWaiting=0,r.tId=r.id,r.win=n.win||e.config.win},s._lastId=0,s.prototype={_state:"new",abort:function(e){this._pending=null,this._pendingCSS=null,this._pollTimer=clearTimeout(this._pollTimer),this._queue=[],this._reqsWaiting=0,this.errors.push({error:e||"Aborted"}),this._finish()},execute:function(e){var t=this,n=t.requests,r=t._state,i,s,o,u;if(r==="done"){e&&e(t.errors.length?t.errors:null,t);return}e&&t._callbacks.push(e);if(r==="executing")return;t._state="executing",t._queue=o=[],t.options.timeout&&(t._timeout=setTimeout(function(){t.abort("Timeout")},t.options.timeout)),t._reqsWaiting=n.length;for(i=0,s=n.length;i<s;++i)u=n[i],u.async||u.type==="css"?t._insert(u):o.push(u);t._next()},purge:function(){i._purge(this.nodes)},_createNode:function(e,t,n){var i=n.createElement(e),s,o;r||(o=n.createElement("div"),o.setAttribute("class","a"),r=o.className==="a"?{}:{"for":"htmlFor","class":"className"});for(s in t)t.hasOwnProperty(s)&&i.setAttribute(r[s]||s,t[s]);return i},_finish:function(){var e=this.errors.length?this.errors:null,t=this.options,n=t.context||this,r,i,s;if(this._state==="done")return;this._state="done";for(i=0,s=this._callbacks.length;i<s;++i)this._callbacks[i].call(n,e,this);r=this._getEventData(),e?(t.onTimeout&&e[e.length-1].error==="Timeout"&&t.onTimeout.call(n,r),t.onFailure&&t.onFailure.call(n,r)):t.onSuccess&&t.onSuccess.call(n,r),t.onEnd&&t.onEnd.call(n,r),t._onFinish&&t._onFinish()},_getEventData:function(t){return t?e.merge(this,{abort:this.abort,purge:this.purge,request:t,url:t.url,win:t.win}):this},_getInsertBefore:function(t){var n=t.doc,r=t.insertBefore,s,o,u;return r?typeof r=="string"?n.getElementById(r):r:(s=i._insertCache,u=e.stamp(n),(r=s[u])?r:(r=n.getElementsByTagName("base")[0])?s[u]=r:(r=n.head||n.getElementsByTagName("head")[0],r?(r.appendChild(n.createTextNode("")),s[u]=r.lastChild):s[u]=n.getElementsByTagName("script")[0]))},_insert:function(t){function c(){u._progress("Failed to load "+t.url,t)}function h(){f&&clearTimeout(f),u._progress(null,t)}var n=i._env,r=this._getInsertBefore(t),s=t.type==="js",o=t.node,u=this,a=e.UA,f,l;o||(s?l="script":!n.cssLoad&&a.gecko?l="style":l="link",o=t.node=this._createNode(l,t.attributes,t.doc)),s?(o.setAttribute("src",t.url),t.async?o.async=!0:(n.async&&(o.async=!1),n.preservesScriptOrder||(this._pending=t))):!n.cssLoad&&a.gecko?o.innerHTML=(t.attributes.charset?'@charset "'+t.attributes.charset+'";':"")+'@import "'+t.url+'";':o.setAttribute("href",t.url),s&&a.ie&&(a.ie<9||document.documentMode&&document.documentMode<9)?o.onreadystatechange=function(){/loaded|complete/.test(o.readyState)&&(o.onreadystatechange=null,h())}:!s&&!n.cssLoad?this._poll(t):(a.ie>=10?(o.onerror=function(){setTimeout(c,0)},o.onload=function(){setTimeout(h,0)}):(o.onerror=c,o.onload=h),!n.cssFail&&!s&&(f=setTimeout(c,t.timeout||3e3))),this.nodes.push(o),r.parentNode.insertBefore(o,r)},_next:function(){if(this._pending)return;this._queue.length?this._insert(this._queue.shift()):this._reqsWaiting||this._finish()},_poll:function(t){var n=this,r=n._pendingCSS,i=e.UA.webkit,s,o,u,a,f,l;if(t){r||(r=n._pendingCSS=[]),r.push(t);if(n._pollTimer)return}n._pollTimer=null;for(s=0;s<r.length;++s){f=r[s];if(i){l=f.doc.styleSheets,u=l.length,a=f.node.href;while(--u>=0)if(l[u].href===a){r.splice(s,1),s-=1,n._progress(null,f);break}}else try{o=!!f.node.sheet.cssRules,r.splice(s,1),s-=1,n._progress(null,f)}catch(c){}}r.length&&(n._pollTimer=setTimeout(function(){n._poll.call(n)},n.options.pollInterval))},_progress:function(e,t){var n=this.options;e&&(t.error=e,this.errors.push({error:e,request:t})),t.node._yuiget_finished=t.finished=!0,n.onProgress&&n.onProgress.call(n.context||this,this._getEventData(t)),t.autopurge&&(i._autoPurge(this.options.purgethreshold),i._purgeNodes.push(t.node)),this._pending===t&&(this._pending=null),this._reqsWaiting-=1,this._next()}}},"3.7.3",{requires:["yui-base"]}),YUI.add("features",function(e,t){var n={};e.mix(e.namespace("Features"),{tests:n,add:function(e,t,r){n[e]=n[e]||{},n[e][t]=r},all:function(t,r){var i=n[t],s=[];return i&&e.Object.each(i,function(n,i){s.push(i+":"+(e.Features.test(t,i,r)?1:0))}),s.length?s.join(";"):""},test:function(t,r,i){i=i||[];var s,o,u,a=n[t],f=a&&a[r];return!f||(s=f.result,e.Lang.isUndefined(s)&&(o=f.ua,o&&(s=e.UA[o]),u=f.test,u&&(!o||s)&&(s=u.apply(e,i)),f.result=s)),s}});var r=e.Features.add;r("load","0",{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"}),r("load","1",{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"}),r("load","2",{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"}),r("load","3",{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"}),r("load","4",{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"}),r("load","5",{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"}),r("load","6",{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","7",{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}),r("load","8",{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","9",{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}),r("load","10",{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","11",{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}),r("load","12",{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"}),r("load","13",{name:"io-nodejs",trigger:"io-base",ua:"nodejs"}),r("load","14",{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"}),r("load","15",{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"}),r("load","16",{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"}),r("load","17",{name:"widget-base-ie",trigger:"widget-base",ua:"ie"}),r("load","18",{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}),r("load","19",{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"})},"3.7.3",{requires:["yui-base"]}),YUI.add("intl-base",function(e,t){var n=/[, ]/;e.mix(e.namespace("Intl"),{lookupBestLang:function(t,r){function a(e){var t;for(t=0;t<r.length;t+=1)if(e.toLowerCase()===r[t].toLowerCase())return r[t]}var i,s,o,u;e.Lang.isString(t)&&(t=t.split(n));for(i=0;i<t.length;i+=1){s=t[i];if(!s||s==="*")continue;while(s.length>0){o=a(s);if(o)return o;u=s.lastIndexOf("-");if(!(u>=0))break;s=s.substring(0,u),u>=2&&s.charAt(u-2)==="-"&&(s=s.substring(0,u-2))}}return""}})},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-log",function(e,t){var n=e,r="yui:log",i="undefined",s={debug:1,info:1,warn:1,error:1};n.log=function(e,t,o,u){var a,f,l,c,h,p=n,d=p.config,v=p.fire?p:YUI.Env.globalEvents;return d.debug&&(o=o||"",typeof o!="undefined"&&(f=d.logExclude,l=d.logInclude,!l||o in l?l&&o in l?a=!l[o]:f&&o in f&&(a=f[o]):a=1),a||(d.useBrowserConsole&&(c=o?o+": "+e:e,p.Lang.isFunction(d.logFn)?d.logFn.call(p,e,t,o):typeof console!=i&&console.log?(h=t&&console[t]&&t in s?t:"log",console[h](c)):typeof opera!=i&&opera.postError(c)),v&&!u&&(v==p&&!v.getEvent(r)&&v.publish(r,{broadcast:2}),v.fire(r,{msg:e,cat:t,src:o})))),p},n.message=function(){return n.log.apply(n,arguments)}},"3.7.3",{requires:["yui-base"]}),YUI.add("yui-later",function(e,t){var n=[];e.later=function(t,r,i,s,o){t=t||0,s=e.Lang.isUndefined(s)?n:e.Array(s),r=r||e.config.win||e;var u=!1,a=r&&e.Lang.isString(i)?r[i]:i,f=function(){u||(a.apply?a.apply(r,s||n):a(s[0],s[1],s[2],s[3]))},l=o?setInterval(f,t):setTimeout(f,t);return{id:l,interval:o,cancel:function(){u=!0,this.interval?clearInterval(l):clearTimeout(l)}}},e.Lang.later=e.later},"3.7.3",{requires:["yui-base"]}),YUI.add("loader-base",function(e,t){YUI.Env[e.version]||function(){var t=e.version,n="/build/",r=t+n,i=e.Env.base,s="gallery-2012.10.10-19-59",o="2in3",u="4",a="2.9.0",f=i+"combo?",l={version:t,root:r,base:e.Env.base,comboBase:f,skin:{defaultSkin:"sam",base:"assets/skins/",path:"skin.css",after:["cssreset","cssfonts","cssgrids","cssbase","cssreset-context","cssfonts-context"]},groups:{},patterns:{}},c=l.groups,h=function(e,t,r){var s=o+"."+(e||u)+"/"+(t||a)+n,l=r&&r.base?r.base:i,h=r&&r.comboBase?r.comboBase:f;c.yui2.base=l+s,c.yui2.root=s,c.yui2.comboBase=h},p=function(e,t){var r=(e||s)+n,o=t&&t.base?t.base:i,u=t&&t.comboBase?t.comboBase:f;c.gallery.base=o+r,c.gallery.root=r,c.gallery.comboBase=u};c[t]={},c.gallery={ext:!1,combine:!0,comboBase:f,update:p,patterns:{"gallery-":{},"lang/gallery-":{},"gallerycss-":{type:"css"}}},c.yui2={combine:!0,ext:!1,comboBase:f,update:h,patterns:{"yui2-":{configFn:function(e){/-skin|reset|fonts|grids|base/.test(e.name)&&(e.type="css",e.path=e.path.replace(/\.js/,".css"),e.path=e.path.replace(/\/yui2-skin/,"/assets/skins/sam/yui2-skin"))}}}},p(),h(),YUI.Env[t]=l}();var n={},r=[],i=1024,s=YUI.Env,o=s._loaded,u="css",a="js",f="intl",l="sam",c=e.version,h="",p=e.Object,d=p.each,v=e.Array,m=s._loaderQueue,g=s[c],y="skin-",b=e.Lang,w=s.mods,E,S=function(e,t,n,r){var i=e+"/"+t;return r||(i+="-min"),i+="."+(n||u),i};YUI.Env._cssLoaded||(YUI.Env._cssLoaded={}),e.Env.meta=g,e.Loader=function(t){var n=this;t=t||{},E=g.md5,n.context=e,n.base=e.Env.meta.base+e.Env.meta.root,n.comboBase=e.Env.meta.comboBase,n.combine=t.base&&t.base.indexOf(n.comboBase.substr(0,20))>-1,n.comboSep="&",n.maxURLLength=i,n.ignoreRegistered=t.ignoreRegistered,n.root=e.Env.meta.root,n.timeout=0,n.forceMap={},n.allowRollup=!1,n.filters={},n.required={},n.patterns={},n.moduleInfo={},n.groups=e.merge(e.Env.meta.groups),n.skin=e.merge(e.Env.meta.skin),n.conditions={},n.config=t,n._internal=!0,n._populateCache(),n.loaded=o[c],n.async=!0,n._inspectPage(),n._internal=!1,n._config(t),n.forceMap=n.force?e.Array.hash(n.force):{},n.testresults=null,e.config.tests&&(n.testresults=e.config.tests),n.sorted=[],n.dirty=!0,n.inserted={},n.skipped={},n.tested={},n.ignoreRegistered&&n._resetModules()},e.Loader.prototype={_populateCache:function(){var t=this,n=g.modules,r=s._renderedMods,i;if(r&&!t.ignoreRegistered){for(i in r)r.hasOwnProperty(i)&&(t.moduleInfo[i]=e.merge(r[i]));r=s._conditions;for(i in r)r.hasOwnProperty(i)&&(t.conditions[i]=e.merge(r[i]))}else for(i in n)n.hasOwnProperty(i)&&t.addModule(n[i],i)},_resetModules:function(){var e=this,t,n,r,i,s;for(t in e.moduleInfo)if(e.moduleInfo.hasOwnProperty(t)){r=e.moduleInfo[t],i=r.name,s=YUI.Env.mods[i]?YUI.Env.mods[i].details:null,s&&(e.moduleInfo[i]._reset=!0,e.moduleInfo[i].requires=s.requires||[],e.moduleInfo[i].optional=s.optional||[],e.moduleInfo[i].supersedes=s.supercedes||[]);if(r.defaults)for(n in r.defaults)r.defaults.hasOwnProperty(n)&&r[n]&&(r[n]=r.defaults[n]);delete r.langCache,delete r.skinCache,r.skinnable&&e._addSkin(e.skin.defaultSkin,r.name)}},REGEX_CSS:/\.css(?:[?;].*)?$/i,FILTER_DEFS:{RAW:{searchExp:"-min\\.js",replaceStr:".js"},DEBUG:{searchExp:"-min\\.js",replaceStr:"-debug.js"},COVERAGE:{searchExp:"-min\\.js",replaceStr:"-coverage.js"}},_inspectPage:function(){var e=this,t,n,r,i,s;for(s in e.moduleInfo)e.moduleInfo.hasOwnProperty(s)&&(t=e.moduleInfo[s],t.type&&t.type===u&&e.isCSSLoaded(t.name)&&(e.loaded[s]=!0));for(s in w)w.hasOwnProperty(s)&&(t=w[s],t.details&&(n=e.moduleInfo[t.name],r=t.details.requires,i=n&&n.requires,n?!n._inspected&&r&&i.length!==r.length&&delete n.expanded:n=e.addModule(t.details,s),n._inspected=!0))},_requires:function(e,t){var n,r,i,s,o=this.moduleInfo,a=o[e],f=o[t];if(!a||!f)return!1;r=a.expanded_map,i=a.after_map;if(i&&t in i)return!0;i=f.after_map;if(i&&e in i)return!1;s=o[t]&&o[t].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(e,s[n]))return!0;s=o[e]&&o[e].supersedes;if(s)for(n=0;n<s.length;n++)if(this._requires(t,s[n]))return!1;return r&&t in r?!0:a.ext&&a.type===u&&!f.ext&&f.type===u?!0:!1},_config:function(t){var n,r,i,s,o,u,a,f=this,l=[],c;if(t)for(n in t)if(t.hasOwnProperty(n)){i=t[n];if(n==="require")f.require(i);else if(n==="skin")typeof i=="string"&&(f.skin.defaultSkin=t.skin,i={defaultSkin:i}),e.mix(f.skin,i,!0);else if(n==="groups"){for(r in i)if(i.hasOwnProperty(r)){a=r,u=i[r],f.addGroup(u,a);if(u.aliases)for(s in u.aliases)u.aliases.hasOwnProperty(s)&&f.addAlias(u.aliases[s],s)}}else if(n==="modules")for(r in i)i.hasOwnProperty(r)&&f.addModule(i[r],r);else if(n==="aliases")for(r in i)i.hasOwnProperty(r)&&f.addAlias(i[r],r);else n==="gallery"?this.groups.gallery.update(i,t):n==="yui2"||n==="2in3"?this.groups.yui2.update(t["2in3"],t.yui2,t):f[n]=i}o=f.filter,b.isString(o)&&(o=o.toUpperCase(),f.filterName=o,f.filter=f.FILTER_DEFS[o],o==="DEBUG"&&f.require("yui-log","dump"));if(f.filterName&&f.coverage&&f.filterName==="COVERAGE"&&b.isArray(f.coverage)&&f.coverage.length){for(n=0;n<f.coverage.length;n++)c=f.coverage[n],f.moduleInfo[c]&&f.moduleInfo[c].use?l=[].concat(l,f.moduleInfo[c].use):l.push(c);f.filters=f.filters||{},e.Array.each(l,function(e){f.filters[e]=f.FILTER_DEFS.COVERAGE}),f.filterName="RAW",f.filter=f.FILTER_DEFS[f.filterName]}},formatSkin:function(e,t){var n=y+e;return t&&(n=n+"-"+t),n},_addSkin:function(e,t,n){var r,i,s,o,u=this.moduleInfo,a=this.skin,f=u[t]&&u[t].ext;return t&&(s=this.formatSkin(e,t),u[s]||(r=u[t],i=r.pkg||t,o={skin:!0,name:s,group:r.group,type:"css",after:a.after,path:(n||i)+"/"+a.base+e+"/"+t+".css",ext:f},r.base&&(o.base=r.base),r.configFn&&(o.configFn=r.configFn),this.addModule(o,s))),s},addAlias:function(e,t){YUI.Env.aliases[t]=e,this.addModule({name:t,use:e})},addGroup:function(e,t){var n=e.modules,r=this,i,s;t=t||e.name,e.name=t,r.groups[t]=e;if(e.patterns)for(i in e.patterns)e.patterns.hasOwnProperty(i)&&(e.patterns[i].group=t,r.patterns[i]=e.patterns[i]);if(n)for(i in n)n.hasOwnProperty(i)&&(s=n[i],typeof s=="string"&&(s={name:i,fullpath:s}),s.group=t,r.addModule(s,i))},addModule:function(t,n){n=n||t.name,typeof t=="string"&&(t={name:n,fullpath:t});var r,i,o,f,l,c,p,d,m,g,y,b,w,E,x,T,N,C,k,L,A,O,M=this.conditions,_;this.moduleInfo[n]&&this.moduleInfo[n].temp&&(t=e.merge(this.moduleInfo[n],t)),t.name=n;if(!t||!t.name)return null;t.type||(t.type=a,O=t.path||t.fullpath,O&&this.REGEX_CSS.test(O)&&(t.type=u)),!t.path&&!t.fullpath&&(t.path=S(n,n,t.type)),t.supersedes=t.supersedes||t.use,t.ext="ext"in t?t.ext:this._internal?!1:!0,r=t.submodules,this.moduleInfo[n]=t,t.requires=t.requires||[];if(this.requires)for(i=0;i<this.requires.length;i++)t.requires.push(this.requires[i]);if(t.group&&this.groups&&this.groups[t.group]){A=this.groups[t.group];if(A.requires)for(i=0;i<A.requires.length;i++)t.requires.push(A.requires[i])}t.defaults||(t.defaults={requires:t.requires?[].concat(t.requires):null,supersedes:t.supersedes?[].concat(t.supersedes):null,optional:t.optional?[].concat(t.optional):null}),t.skinnable&&t.ext&&t.temp&&(k=this._addSkin(this.skin.defaultSkin,n),t.requires.unshift(k)),t.requires.length&&(t.requires=this.filterRequires(t.requires)||[]);if(!t.langPack&&t.lang){y=v(t.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b))}if(r){l=t.supersedes||[],o=0;for(i in r)if(r.hasOwnProperty(i)){c=r[i],c.path=c.path||S(n,i,t.type),c.pkg=n,c.group=t.group,c.supersedes&&(l=l.concat(c.supersedes)),p=this.addModule(c,i),l.push(i);if(p.skinnable){t.skinnable=!0,C=this.skin.overrides;if(C&&C[i])for(g=0;g<C[i].length;g++)k=this._addSkin(C[i][g],i,n),l.push(k);k=this._addSkin(this.skin.defaultSkin,i,n),l.push(k)}if(c.lang&&c.lang.length){y=v(c.lang);for(g=0;g<y.length;g++)T=y[g],b=this.getLangPackName(T,n),w=this.getLangPackName(T,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),E=E||v.hash(p.supersedes),w in E||p.supersedes.push(w),t.lang=t.lang||[],x=x||v.hash(t.lang),T in x||t.lang.push(T),b=this.getLangPackName(h,n),w=this.getLangPackName(h,i),p=this.moduleInfo[b],p||(p=this._addLangPack(T,t,b)),w in E||p.supersedes.push(w)}o++}t.supersedes=v.dedupe(l),this.allowRollup&&(t.rollup=o<4?o:Math.min(o-1,4))}d=t.plugins;if(d)for(i in d)d.hasOwnProperty(i)&&(m=d[i],m.pkg=n,m.path=m.path||S(n,i,t.type),m.requires=m.requires||[],m.group=t.group,this.addModule(m,i),t.skinnable&&this._addSkin(this.skin.defaultSkin,i,n));if(t.condition){f=t.condition.trigger,YUI.Env.aliases[f]&&(f=YUI.Env.aliases[f]),e.Lang.isArray(f)||(f=[f]);for(i=0;i<f.length;i++)_=f[i],L=t.condition.when,M[_]=M[_]||{},M[_][n]=t.condition,L&&L!=="after"?L==="instead"&&(t.supersedes=t.supersedes||[],t.supersedes.push(_)):(t.after=t.after||[],t.after.push(_))}return t.supersedes&&(t.supersedes=this.filterRequires(t.supersedes)),t.after&&(t.after=this.filterRequires(t.after),t.after_map=v.hash(t.after)),t.configFn&&(N=t.configFn(t),N===!1&&(delete this.moduleInfo[n],delete s._renderedMods[n],t=null)),t&&(s._renderedMods||(s._renderedMods={}),s._renderedMods[n]=e.mix(s._renderedMods[n]||{},t),s._conditions=M),t},require:function(t){var n=typeof t=="string"?v(arguments):t;this.dirty=!0,this.required=e.merge(this.required,v.hash(this.filterRequires(n))),this._explodeRollups()},_explodeRollups:function(){var e=this,t,n,r,i,s,o,u,a=e.required;if(!e.allowRollup){for(r in a)if(a.hasOwnProperty(r)){t=e.getModule(r);if(t&&t.use){o=t.use.length;for(i=0;i<o;i++){n=e.getModule(t.use[i]);if(n&&n.use){u=n.use.length;for(s=0;s<u;s++)a[n.use[s]]=!0}else a[t.use[i]]=!0}}}e.required=a}},filterRequires:function(t){if(t){e.Lang.isArray(t)||(t=[t]),t=e.Array(t);var n=[],r,i,s,o;for(r=0;r<t.length;r++){i=this.getModule(t[r]);if(i&&i.use)for(s=0;s<i.use.length;s++)o=this.getModule(i.use[s]),o&&o.use&&o.name!==i.name?n=e.Array.dedupe([].concat(n,this.filterRequires(o.use))):n.push(i.use[s]);else n.push(t[r])}t=n}return t},getRequires:function(t){if(!t)return r;if(t._parsed)return t.expanded||r;var n,i,s,o,u,a,l=this.testresults,c=t.name,m,g=w[c]&&w[c].details,y,b,E,S,x,T,N,C,k,L,A=t.lang||t.intl,O=this.moduleInfo,M=e.Features&&e.Features.tests.load,_,D;t.temp&&g&&(x=t,t=this.addModule(g,c),t.group=x.group,t.pkg=x.pkg,delete t.expanded),D=!!this.lang&&t.langCache!==this.lang||t.skinCache!==this.skin.defaultSkin;if(t.expanded&&!D)return t.expanded;y=[],_={},S=this.filterRequires(t.requires),t.lang&&(y.unshift("intl"),S.unshift("intl"),A=!0),T=this.filterRequires(t.optional),t._parsed=!0,t.langCache=this.lang,t.skinCache=this.skin.defaultSkin;for(n=0;n<S.length;n++)if(!_[S[n]]){y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}S=this.filterRequires(t.supersedes);if(S)for(n=0;n<S.length;n++)if(!_[S[n]]){t.submodules&&y.push(S[n]),_[S[n]]=!0,i=this.getModule(S[n]);if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}if(T&&this.loadOptional)for(n=0;n<T.length;n++)if(!_[T[n]]){y.push(T[n]),_[T[n]]=!0,i=O[T[n]];if(i){o=this.getRequires(i),A=A||i.expanded_map&&f in i.expanded_map;for(s=0;s<o.length;s++)y.push(o[s])}}m=this.conditions[c];if(m){t._parsed=!1;if(l&&M)d(l,function(e,t){var n=M[t].name;!_[n]&&M[t].trigger===c&&e&&M[t]&&(_[n]=!0,y.push(n))});else for(n in m)if(m.hasOwnProperty(n)&&!_[n]){E=m[n],b=E&&(!E.ua&&!E.test||E.ua&&e.UA[E.ua]||E.test&&E.test(e,S));if(b){_[n]=!0,y.push(n),i=this.getModule(n);if(i){o=this.getRequires(i);for(s=0;s<o.length;s++)y.push(o[s])}}}}if(t.skinnable){C=this.skin.overrides;for(n in YUI.Env.aliases)YUI.Env.aliases.hasOwnProperty(n)&&e.Array.indexOf(YUI.Env.aliases[n],c)>-1&&(k=n);if(C&&(C[c]||k&&C[k])){L=c,C[k]&&(L=k);for(n=0;n<C[L].length;n++)N=this._addSkin(C[L][n],c),this.isCSSLoaded(N,this._boot)||y.push(N)}else N=this._addSkin(this.skin.defaultSkin,c),this.isCSSLoaded(N,this._boot)||y.push(N)}return t._parsed=!1,A&&(t.lang&&!t.langPack&&e.Intl&&(a=e.Intl.lookupBestLang(this.lang||h,t.lang),u=this.getLangPackName(a,c),u&&y.unshift(u)),y.unshift(f)),t.expanded_map=v.hash(y),t.expanded=p.keys(t.expanded_map),t.expanded},isCSSLoaded:function(t,n){if(!t||!YUI.Env.cssStampEl||!n&&this.ignoreRegistered)return!1;var r=YUI.Env.cssStampEl,i=!1,s=YUI.Env._cssLoaded[t],o=r.currentStyle;return s!==undefined?s:(r.className=t,o||(o=e.config.doc.defaultView.getComputedStyle(r,null)),o&&o.display==="none"&&(i=!0),r.className="",YUI.Env._cssLoaded[t]=i,i)},getProvides:function(t){var r=this.getModule(t),i,s;return r?(r&&!r.provides&&(i={},s=r.supersedes,s&&v.each(s,function(t){e.mix(i,this.getProvides(t))},this),i[t]=!0,r.provides=i),r.provides):n},calculate:function(e,t){if(e||t||this.dirty)e&&this._config(e),this._init||this._setup(),this._explode(),this.allowRollup?this._rollup():this._explodeRollups(),this._reduce(),this._sort()},_addLangPack:function(t,n,r){var i=n.name,s,o,u=this.moduleInfo[r];return u||(s=S(n.pkg||i,r,a,!0),o={path:s,intl:!0,langPack:!0,ext:n.ext,group:n.group,supersedes:[]},n.root&&(o.root=n.root),n.base&&(o.base=n.base),n.configFn&&(o.configFn=n.configFn),this.addModule(o,r),t&&(e.Env.lang=e.Env.lang||{},e.Env.lang[t]=e.Env.lang[t]||{},e.Env.lang[t][i]=!0)),this.moduleInfo[r]},_setup:function(){var t=this.moduleInfo,n,r,i,o,u,a;for(n in t)t.hasOwnProperty(n)&&(o=t[n],o&&(o.requires=v.dedupe(o.requires),o.lang&&(a=this.getLangPackName(h,n),this._addLangPack(null,o,a))));u={},this.ignoreRegistered||e.mix(u,s.mods),this.ignore&&e.mix(u,v.hash(this.ignore));for(i in u)u.hasOwnProperty(i)&&e.mix(u,this.getProvides(i));if(this.force)for(r=0;r<this.force.length;r++)this.force[r]in u&&delete u[this.force[r]];e.mix(this.loaded,u),this._init=!0},getLangPackName:function(e,t){return"lang/"+t+(e?"_"+e:"")},_explode:function(){var t=this.required,n,r,i={},s=this,o,u;s.dirty=!1,s._explodeRollups(),t=s.required;for(o in t)t.hasOwnProperty(o)&&(i[o]||(i[o]=!0,n=s.getModule(o),n&&(u=n.expound,u&&(t[u]=s.getModule(u),r=s.getRequires(t[u]),e.mix(t,v.hash(r))),r=s.getRequires(n),e.mix(t,v.hash(r)))))},_patternTest:function(e,t){return e.indexOf(t)>-1},getModule:function(t){if(!t)return null;var n,r,i,s=this.moduleInfo[t],o=this.patterns;if(!s||s&&s.ext)for(i in o)if(o.hasOwnProperty(i)){n=o[i],n.test||(n.test=this._patternTest);if(n.test(t,i)){r=n;break}}return s?r&&s&&r.configFn&&!s.configFn&&(s.configFn=r.configFn,s.configFn(s)):r&&(n.action?n.action.call(this,t,i):(s=this.addModule(e.merge(r),t),r.configFn&&(s.configFn=r.configFn),s.temp=!0)),s},_rollup:function(){},_reduce:function(e){e=e||this.required;var t,n,r,i,s=this.loadType,o=this.ignore?v.hash(this.ignore):!1;for(t in e)if(e.hasOwnProperty(t)){i=this.getModule(t),((this.loaded[t]||w[t])&&!this.forceMap[t]&&!this.ignoreRegistered||s&&i&&i.type!==s)&&delete e[t],o&&o[t]&&delete e[t],r=i&&i.supersedes;if(r)for(n=0;n<r.length;n++)r[n]in e&&delete e[r[n]]}return e},_finish:function(e,t){m.running=!1;var n=this.onEnd;n&&n.call(this.context,{msg:e,data:this.data,success:t}),this._continue()},_onSuccess:function(){var t=this,n=e.merge(t.skipped),r,i=[],s=t.requireRegistration,o,u,f,l;for(f in n)n.hasOwnProperty(f)&&delete t.inserted[f];t.skipped={};for(f in t.inserted)t.inserted.hasOwnProperty(f)&&(l=t.getModule(f),!l||!s||l.type!==a||f in YUI.Env.mods?e.mix(t.loaded,t.getProvides(f)):i.push(f));r=t.onSuccess,u=i.length?"notregistered":"success",o=!i.length,r&&r.call(t.context,{msg:u,data:t.data,success:o,failed:i,skipped:n}),t._finish(u,o)},_onProgress:function(e){var t=this,n;if(e.data&&e.data.length)for(n=0;n<e.data.length;n++)e.data[n]=t.getModule(e.data[n].name);t.onProgress&&t.onProgress.call(t.context,{name:e.url,data:e.data})},_onFailure:function(e){var t=this.onFailure,n=[],r=0,i=e.errors.length;for(r;r<i;r++)n.push(e.errors[r].error);n=n.join(","),t&&t.call(this.context,{msg:n,data:this.data,success:!1}),this._finish(n,!1)},_onTimeout:function(){var e=this.onTimeout;e&&e.call(this.context,{msg:"timeout",data:this.data,success:!1})},_sort:function(){var e=p.keys(this.required),t={},n=0,r,i,s,o,u,a,f;for(;;){r=e.length,a=!1;for(o=n;o<r;o++){i=e[o];for(u=o+1;u<r;u++){f=i+e[u];if(!t[f]&&this._requires(i,e[u])){s=e.splice(u,1),e.splice(o,0,s[0]),t[f]=!0,a=!0;break}}if(a)break;n++}if(!a)break}this.sorted=e},_insert:function(t,n,r,i){t&&this._config(t);var s=this.resolve(!i),o=this,f=0,l=0,c={},h,p;o._refetch=[],r&&(s[r===a?u:a]=[]),o.fetchCSS||(s.css=[]),s.js.length&&f++,s.css.length&&f++,p=function(t){l++;var n={},r=0,i=0,s="",u,a,p;if(t&&t.errors)for(r=0;r<t.errors.length;r++)t.errors[r].request?s=t.errors[r].request.url:s=t.errors[r],n[s]=s;if(t&&t.data&&t.data.length&&t.type==="success")for(r=0;r<t.data.length;r++){o.inserted[t.data[r].name]=!0;if(t.data[r].lang||t.data[r].skinnable)delete o.inserted[t.data[r].name],o._refetch.push(t.data[r].name)}if(l===f){o._loading=null;if(o._refetch.length){for(r=0;r<o._refetch.length;r++){h=o.getRequires(o.getModule(o._refetch[r]));for(i=0;i<h.length;i++)o.inserted[h[i]]||(c[h[i]]=h[i])}c=e.Object.keys(c);if(c.length){o.require(c),p=o.resolve(!0);if(p.cssMods.length){for(r=0;r<p.cssMods.length;r++)a=p.cssMods[r].name,delete YUI.Env._cssLoaded[a],o.isCSSLoaded(a)&&(o.inserted[a]=!0,delete o.required[a]);o.sorted=[],o._sort()}t=null,o._insert()}}t&&t.fn&&(u=t.fn,delete t.fn,u.call(o,t))}},this._loading=!0;if(!s.js.length&&!s.css.length){l=-1,p({fn:o._onSuccess});return}s.css.length&&e.Get.css(s.css,{data:s.cssMods,attributes:o.cssAttributes,insertBefore:o.insertBefore,charset:o.charset,timeout:o.timeout,context:o,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}}),s.js.length&&e.Get.js(s.js,{data:s.jsMods,insertBefore:o.insertBefore,attributes:o.jsAttributes,charset:o.charset,timeout:o.timeout,autopurge:!1,context:o,async:o.async,onProgress:function(e){o._onProgress.call(o,e)},onTimeout:function(e){o._onTimeout.call(o,e)},onSuccess:function(e){e.type="success",e.fn=o._onSuccess,p.call(o,e)},onFailure:function(e){e.type="failure",e.fn=o._onFailure,p.call(o,e)}})},_continue:function(){!m.running&&m.size()>0&&(m.running=!0,m.next()())},insert:function(t,n,r){var i=this,s=e.merge(this);delete s.require,delete s.dirty,m.add(function(){i._insert(s,t,n,r)}),this._continue()},loadNext:function(){return},_filter:function(e,t,n){var r=this.filter,i=t&&t in this.filters,s=i&&this.filters[t],o=n||(this.moduleInfo[t]?this.moduleInfo[t].group:null);return o&&this.groups[o]&&this.groups[o].filter&&(s=this.groups[o].filter,i=!0),e&&(i&&(r=b.isString(s)?this.FILTER_DEFS[s.toUpperCase()]||null:s),r&&(e=e.replace(new RegExp(r.searchExp,"g"),r.replaceStr))),e},_url:function(e,t,n){return this._filter((n||this.base||"")+e,t)},resolve:function(e,t){var r,s,o,f,c,h,p,d,v,m,g,y,w,E,S=[],x,T,N={},C=this,k,A,O=C.ignoreRegistered?{}:C.inserted,M={js:[],jsMods:[],css:[],cssMods:[]},_=C.loadType||"js",D;(C.skin.overrides||C.skin.defaultSkin!==l||C.ignoreRegistered)&&C._resetModules(),e&&C.calculate(),t=t||C.sorted,D=function(e){if(e){c=e.group&&C.groups[e.group]||n,c.async===!1&&(e.async=c.async),f=e.fullpath?C._filter(e.fullpath,t[s]):C._url(e.path,t[s],c.base||e.base);if(e.attributes||e.async===!1)f={url:f,async:e.async},e.attributes&&(f.attributes=e.attributes);M[e.type].push(f),M[e.type+"Mods"].push(e)}},r=t.length,y=C.comboBase,f=y,m={};for(s=0;s<r;s++){v=y,o=C.getModule(t[s]),h=o&&o.group,c=C.groups[h];if(h&&c){if(!c.combine||o.fullpath){D(o);continue}o.combine=!0,c.comboBase&&(v=c.comboBase),"root"in c&&b.isValue(c.root)&&(o.root=c.root),o.comboSep=c.comboSep||C.comboSep,o.maxURLLength=c.maxURLLength||C.maxURLLength}else if(!C.combine){D(o);continue}m[v]=m[v]||[],m[v].push(o)}for(p in m)if(m.hasOwnProperty(p)){N[p]=N[p]||{js:[],jsMods:[],css:[],cssMods:[]},f=p,g=m[p],r=g.length;if(r)for(s=0;s<r;s++){if(O[g[s]])continue;o=g[s],o&&(o.combine||!o.ext)?(N[p].comboSep=o.comboSep,N[p].group=o.group,N[p].maxURLLength=o.maxURLLength,d=(b.isValue(o.root)?o.root:C.root)+(o.path||o.fullpath),d=C._filter(d,o.name),N[p][o.type].push(d),N[p][o.type+"Mods"].push(o)):g[s]&&D(g[s])}}for(p in N){w=p,k=N[w].comboSep||C.comboSep,A=N[w].maxURLLength||C.maxURLLength;for(_ in N[w])if(_===a||_===u){E=N[w][_],g=N[w][_+"Mods"],r=E.length,x=w+E.join(k),T=x.length,A<=w.length&&(A=i);if(r)if(T>A){S=[];for(t=0;t<r;t++)S.push(E[t]),x=w+S.join(k),x.length>A&&(o=S.pop(),x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)),S=[],o&&S.push(o));S.length&&(x=w+S.join(k),M[_].push(C._filter(x,null,N[w].group)))}else M[_].push(C._filter(x,null,N[w].group));M[_+"Mods"]=M[_+"Mods"].concat(g)}}return N=null,M},load:function(e){if(!e)return;var t=this,n=t.resolve(!0);t.data=n,t.onEnd=function(){e.apply(t.context||t,arguments)},t.insert()}}},"3.7.3",{requires:["get","features"]}),YUI.add("loader-rollup",function(e,t){e.Loader.prototype._rollup=function(){var e,t,n,r,i=this.required,s,o=this.moduleInfo,u,a,f;if(this.dirty||!this.rollups){this.rollups={};for(e in o)o.hasOwnProperty(e)&&(n=this.getModule(e),n&&n.rollup&&(this.rollups[e]=n))}for(;;){u=!1;for(e in this.rollups)if(this.rollups.hasOwnProperty(e)&&!i[e]&&(!this.loaded[e]||this.forceMap[e])){n=this.getModule(e),r=n.supersedes||[],s=!1;if(!n.rollup)continue;a=0;for(t=0;t<r.length;t++){f=o[r[t]];if(this.loaded[r[t]]&&!this.forceMap[r[t]]){s=!1;break}if(i[r[t]]&&n.type===f.type){a++,s=a>=n.rollup;if(s)break}}s&&(i[e]=!0,u=!0,this.getRequires(n))}if(!u)break}}},"3.7.3",{requires:["loader-base"]}),YUI.add("loader-yui3",function(e,t){YUI.Env[e.version].modules=YUI.Env[e.version].modules||{"align-plugin":{requires:["node-screen","node-pluginhost"]},anim:{use:["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"]},"anim-base":{requires:["base-base","node-style"]},"anim-color":{requires:["anim-base"]},"anim-curve":{requires:["anim-xy"]},"anim-easing":{requires:["anim-base"]},"anim-node-plugin":{requires:["node-pluginhost","anim-base"]},"anim-scroll":{requires:["anim-base"]},"anim-shape":{requires:["anim-base","anim-easing","anim-color","matrix"]},"anim-shape-transform":{use:["anim-shape"]},"anim-xy":{requires:["anim-base","node-screen"]},app:{use:["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"]},"app-base":{requires:["classnamemanager","pjax-base","router","view"]},"app-content":{requires:["app-base","pjax-content"]},"app-transitions":{requires:["app-base"]},"app-transitions-css":{type:"css"},"app-transitions-native":{condition:{name:"app-transitions-native",test:function(e){var t=e.config.doc,n=t?t.documentElement:null;return n&&n.style?"MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style:!1},trigger:"app-transitions"},requires:["app-transitions","app-transitions-css","parallel","transition"]},"array-extras":{requires:["yui-base"]},"array-invoke":{requires:["yui-base"]},arraylist:{requires:["yui-base"]},"arraylist-add":{requires:["arraylist"]},"arraylist-filter":{requires:["arraylist"]},arraysort:{requires:["yui-base"]},"async-queue":{requires:["event-custom"]},attribute:{use:["attribute-base","attribute-complex"]},"attribute-base":{requires:["attribute-core","attribute-events","attribute-extras"]},"attribute-complex":{requires:["attribute-base"]},"attribute-core":{requires:["oop"]},"attribute-events":{requires:["event-custom"]},"attribute-extras":{requires:["oop"]},autocomplete:{use:["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"]},"autocomplete-base":{optional:["autocomplete-sources"],requires:["array-extras","base-build","escape","event-valuechange","node-base"]},"autocomplete-filters":{requires:["array-extras","text-wordbreak"]},"autocomplete-filters-accentfold":{requires:["array-extras","text-accentfold","text-wordbreak"]},"autocomplete-highlighters":{requires:["array-extras","highlight-base"]},"autocomplete-highlighters-accentfold":{requires:["array-extras","highlight-accentfold"]},"autocomplete-list":{after:["autocomplete-sources"],lang:["en"],requires:["autocomplete-base","event-resize","node-screen","selector-css3","shim-plugin","widget","widget-position","widget-position-align"],skinnable:!0},"autocomplete-list-keys":{condition:{name:"autocomplete-list-keys",test:function(e){return!e.UA.ios&&!e.UA.android},trigger:"autocomplete-list"},requires:["autocomplete-list","base-build"]},"autocomplete-plugin":{requires:["autocomplete-list","node-pluginhost"]},"autocomplete-sources":{optional:["io-base","json-parse","jsonp","yql"],requires:["autocomplete-base"]},base:{use:["base-base","base-pluginhost","base-build"]},"base-base":{after:["attribute-complex"],requires:["base-core","attribute-base"]},"base-build":{requires:["base-base"]},"base-core":{requires:["attribute-core"]},"base-pluginhost":{requires:["base-base","pluginhost"]},button:{requires:["button-core","cssbutton","widget"]},"button-core":{requires:["attribute-core","classnamemanager","node-base"]},"button-group":{requires:["button-plugin","cssbutton","widget"]},"button-plugin":{requires:["button-core","cssbutton","node-pluginhost"]},cache:{use:["cache-base","cache-offline","cache-plugin"]},"cache-base":{requires:["base"]},"cache-offline":{requires:["cache-base","json"]},"cache-plugin":{requires:["plugin","cache-base"]},calendar:{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["calendar-base","calendarnavigator"],skinnable:!0},"calendar-base":{lang:["de","en","fr","ja","nb-NO","pt-BR","ru","zh-HANT-TW"],requires:["widget","substitute","datatype-date","datatype-date-math","cssgrids"],skinnable:!0},calendarnavigator:{requires:["plugin","classnamemanager","datatype-date","node","substitute"],skinnable:!0},charts:{requires:["charts-base"]},"charts-base":{requires:["dom","datatype-number","datatype-date","event-custom","event-mouseenter","event-touch","widget","widget-position","widget-stack","graphics"]},"charts-legend":{requires:["charts-base"]},classnamemanager:{requires:["yui-base"]},"clickable-rail":{requires:["slider-base"]},collection:{use:["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"]},console:{lang:["en","es","ja"],requires:["yui-log","widget"],skinnable:!0},"console-filters":{requires:["plugin","console"],skinnable:!0},controller:{use:["router"]},cookie:{requires:["yui-base"]},"createlink-base":{requires:["editor-base"]},cssbase:{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},"cssbase-context":{after:["cssreset","cssfonts","cssgrids","cssreset-context","cssfonts-context","cssgrids-context"],type:"css"},cssbutton:{type:"css"},cssfonts:{type:"css"},"cssfonts-context":{type:"css"},cssgrids:{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-base":{optional:["cssreset","cssfonts"],type:"css"},"cssgrids-units":{optional:["cssreset","cssfonts"],requires:["cssgrids-base"],type:"css"},cssreset:{type:"css"},"cssreset-context":{type:"css"},dataschema:{use:["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"]},"dataschema-array":{requires:["dataschema-base"]},"dataschema-base":{requires:["base"]},"dataschema-json":{requires:["dataschema-base","json"]},"dataschema-text":{requires:["dataschema-base"]},"dataschema-xml":{requires:["dataschema-base"]},datasource:{use:["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"]},"datasource-arrayschema":{requires:["datasource-local","plugin","dataschema-array"]},"datasource-cache":{requires:["datasource-local","plugin","cache-base"]},"datasource-function":{requires:["datasource-local"]},"datasource-get":{requires:["datasource-local","get"]},"datasource-io":{requires:["datasource-local","io-base"]},"datasource-jsonschema":{requires:["datasource-local","plugin","dataschema-json"]},"datasource-local":{requires:["base"]},"datasource-polling":{requires:["datasource-local"]},"datasource-textschema":{requires:["datasource-local","plugin","dataschema-text"]},"datasource-xmlschema":{requires:["datasource-local","plugin","datatype-xml","dataschema-xml"]},datatable:{use:["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"]},"datatable-base":{requires:["datatable-core","datatable-table","datatable-head","datatable-body","base-build","widget"],skinnable:!0},"datatable-base-deprecated":{requires:["recordset-base","widget","substitute","event-mouseenter"],skinnable:!0},"datatable-body":{requires:["datatable-core","view","classnamemanager"]},"datatable-column-widths":{requires:["datatable-base"]},"datatable-core":{requires:["escape","model-list","node-event-delegate"]},"datatable-datasource":{requires:["datatable-base","plugin","datasource-local"]},"datatable-datasource-deprecated":{requires:["datatable-base-deprecated","plugin","datasource-local"]},"datatable-deprecated":{use:["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"]},"datatable-head":{requires:["datatable-core","view","classnamemanager"]},"datatable-message":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-mutable":{requires:["datatable-base"]},"datatable-scroll":{requires:["datatable-base","datatable-column-widths","dom-screen"],skinnable:!0},"datatable-scroll-deprecated":{requires:["datatable-base-deprecated","plugin"]},"datatable-sort":{lang:["en"],requires:["datatable-base"],skinnable:!0},"datatable-sort-deprecated":{lang:["en"],requires:["datatable-base-deprecated","plugin","recordset-sort"]},"datatable-table":{requires:["datatable-core","datatable-head","datatable-body","view","classnamemanager"]},datatype:{use:["datatype-date","datatype-number","datatype-xml"]},"datatype-date":{use:["datatype-date-parse","datatype-date-format","datatype-date-math"]},"datatype-date-format":{lang:["ar","ar-JO","ca","ca-ES","da","da-DK","de","de-AT","de-DE","el","el-GR","en","en-AU","en-CA","en-GB","en-IE","en-IN","en-JO","en-MY","en-NZ","en-PH","en-SG","en-US","es","es-AR","es-BO","es-CL","es-CO","es-EC","es-ES","es-MX","es-PE","es-PY","es-US","es-UY","es-VE","fi","fi-FI","fr","fr-BE","fr-CA","fr-FR","hi","hi-IN","id","id-ID","it","it-IT","ja","ja-JP","ko","ko-KR","ms","ms-MY","nb","nb-NO","nl","nl-BE","nl-NL","pl","pl-PL","pt","pt-BR","ro","ro-RO","ru","ru-RU","sv","sv-SE","th","th-TH","tr","tr-TR","vi","vi-VN","zh-Hans","zh-Hans-CN","zh-Hant","zh-Hant-HK","zh-Hant-TW"]},"datatype-date-math":{requires:["yui-base"]},"datatype-date-parse":{},"datatype-number":{use:["datatype-number-parse","datatype-number-format"]},"datatype-number-format":{},"datatype-number-parse":{},"datatype-xml":{use:["datatype-xml-parse","datatype-xml-format"]},"datatype-xml-format":{},"datatype-xml-parse":{},dd:{use:["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"]},"dd-constrain":{requires:["dd-drag"]},"dd-ddm":{requires:["dd-ddm-base","event-resize"]},"dd-ddm-base":{requires:["node","base","yui-throttle","classnamemanager"]},"dd-ddm-drop":{requires:["dd-ddm"]},"dd-delegate":{requires:["dd-drag","dd-drop-plugin","event-mouseenter"]},"dd-drag":{requires:["dd-ddm-base"]},"dd-drop":{requires:["dd-drag","dd-ddm-drop"]},"dd-drop-plugin":{requires:["dd-drop"]},"dd-gestures":{condition:{name:"dd-gestures",trigger:"dd-drag",ua:"touchEnabled"},requires:["dd-drag","event-synthetic","event-gestures"]},"dd-plugin":{optional:["dd-constrain","dd-proxy"],requires:["dd-drag"]},"dd-proxy":{requires:["dd-drag"]},"dd-scroll":{requires:["dd-drag"]},dial:{lang:["en","es"],requires:["widget","dd-drag","event-mouseenter","event-move","event-key","transition","intl"],skinnable:!0},dom:{use:["dom-base","dom-screen","dom-style","selector-native","selector"]},"dom-base":{requires:["dom-core"]},"dom-core":{requires:["oop","features"]},"dom-deprecated":{requires:["dom-base"]},"dom-screen":{requires:["dom-base","dom-style"]},"dom-style":{requires:["dom-base"]},"dom-style-ie":{condition:{name:"dom-style-ie",test:function(e){var t=e.Features.test,n=e.Features.add,r=e.config.win,i=e.config.doc,s="documentElement",o=!1;return n("style","computedStyle",{test:function(){return r&&"getComputedStyle"in r}}),n("style","opacity",{test:function(){return i&&"opacity"in i[s].style}}),o=!t("style","opacity")&&!t("style","computedStyle"),o},trigger:"dom-style"},requires:["dom-style"]},dump:{requires:["yui-base"]},editor:{use:["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"]},"editor-base":{requires:["base","frame","node","exec-command","editor-selection"]},"editor-bidi":{requires:["editor-base"]},"editor-br":{requires:["editor-base"]},"editor-lists":{requires:["editor-base"]},"editor-para":{requires:["editor-para-base"]},"editor-para-base":{requires:["editor-base"]},"editor-para-ie":{condition:{name:"editor-para-ie",trigger:"editor-para",ua:"ie",when:"instead"},requires:["editor-para-base"]},"editor-selection":{requires:["node"]},"editor-tab":{requires:["editor-base"]},escape:{requires:["yui-base"]},event:{after:["node-base"],use:["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"]},"event-base":{after:["node-base"],requires:["event-custom-base"]},"event-base-ie":{after:["event-base"],condition:{name:"event-base-ie",test:function(e){var t=e.config.doc&&e.config.doc.implementation;return t&&!t.hasFeature("Events","2.0")},trigger:"node-base"},requires:["node-base"]},"event-contextmenu":{requires:["event-synthetic","dom-screen"]},"event-custom":{use:["event-custom-base","event-custom-complex"]},"event-custom-base":{requires:["oop"]},"event-custom-complex":{requires:["event-custom-base"]},"event-delegate":{requires:["node-base"]},"event-flick":{requires:["node-base","event-touch","event-synthetic"]},"event-focus":{requires:["event-synthetic"]},"event-gestures":{use:["event-flick","event-move"]},"event-hover":{requires:["event-mouseenter"]},"event-key":{requires:["event-synthetic"]},"event-mouseenter":{requires:["event-synthetic"]},"event-mousewheel":{requires:["node-base"]},"event-move":{requires:["node-base","event-touch","event-synthetic"]},"event-outside":{requires:["event-synthetic"]},"event-resize":{requires:["node-base","event-synthetic"]},"event-simulate":{requires:["event-base"]},"event-synthetic":{requires:["node-base","event-custom-complex"]},"event-tap":{requires:["node-base","event-base","event-touch","event-synthetic"]},"event-touch":{requires:["node-base"]},"event-valuechange":{requires:["event-focus","event-synthetic"]},"exec-command":{requires:["frame"]},features:{requires:["yui-base"]},file:{requires:["file-flash","file-html5"]},"file-flash":{requires:["base"]},"file-html5":{requires:["base"]},frame:{requires:["base","node","selector-css3","yui-throttle"]},"gesture-simulate":{requires:["async-queue","event-simulate","node-screen"]},get:{requires:["yui-base"]},graphics:{requires:["node","event-custom","pluginhost","matrix","classnamemanager"]},"graphics-canvas":{condition:{name:"graphics-canvas",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"},requires:["graphics"]},"graphics-canvas-default":{condition:{name:"graphics-canvas-default",test:function(e){var t=e.config.doc,n=e.config.defaultGraphicEngine&&e.config.defaultGraphicEngine=="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return(!i||n)&&r&&r.getContext&&r.getContext("2d")},trigger:"graphics"}},"graphics-svg":{condition:{name:"graphics-svg",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"},requires:["graphics"]},"graphics-svg-default":{condition:{name:"graphics-svg-default",test:function(e){var t=e.config.doc,n=!e.config.defaultGraphicEngine||e.config.defaultGraphicEngine!="canvas",r=t&&t.createElement("canvas"),i=t&&t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");return i&&(n||!r)},trigger:"graphics"}},"graphics-vml":{condition:{name:"graphics-vml",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"},requires:["graphics"]},"graphics-vml-default":{condition:{name:"graphics-vml-default",test:function(e){var t=e.config.doc,n=t&&t.createElement("canvas");return t&&!t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")&&(!n||!n.getContext||!n.getContext("2d"))},trigger:"graphics"}},handlebars:{use:["handlebars-compiler"]},"handlebars-base":{requires:["escape"]},"handlebars-compiler":{requires:["handlebars-base"]},highlight:{use:["highlight-base","highlight-accentfold"]},"highlight-accentfold":{requires:["highlight-base","text-accentfold"]},"highlight-base":{requires:["array-extras","classnamemanager","escape","text-wordbreak"]},history:{use:["history-base","history-hash","history-hash-ie","history-html5"]},"history-base":{requires:["event-custom-complex"]},"history-hash":{after:["history-html5"],requires:["event-synthetic","history-base","yui-later"]},"history-hash-ie":{condition:{name:"history-hash-ie",test:function(e){var t=e.config.doc&&e.config.doc.documentMode;return e.UA.ie&&(!("onhashchange"in e.config.win)||!t||t<8)},trigger:"history-hash"},requires:["history-hash","node-base"]},"history-html5":{optional:["json"],requires:["event-base","history-base","node-base"]},imageloader:{requires:["base-base","node-style","node-screen"]},intl:{requires:["intl-base","event-custom"]},"intl-base":{requires:["yui-base"]},io:{use:["io-base","io-xdr","io-form","io-upload-iframe","io-queue"]},"io-base":{requires:["event-custom-base","querystring-stringify-simple"]},"io-form":{requires:["io-base","node-base"]},"io-nodejs":{condition:{name:"io-nodejs",trigger:"io-base",ua:"nodejs"},requires:["io-base"]},"io-queue":{requires:["io-base","queue-promote"]},"io-upload-iframe":{requires:["io-base","node-base"]},"io-xdr":{requires:["io-base","datatype-xml-parse"]},json:{use:["json-parse","json-stringify"]},"json-parse":{requires:["yui-base"]},"json-stringify":{requires:["yui-base"]},jsonp:{requires:["get","oop"]},"jsonp-url":{requires:["jsonp"]},"lazy-model-list":{requires:["model-list"]},loader:{use:["loader-base","loader-rollup","loader-yui3"]},"loader-base":{requires:["get","features"]},"loader-rollup":{requires:["loader-base"]},"loader-yui3":{requires:["loader-base"]},matrix:{requires:["yui-base"]},model:{requires:["base-build","escape","json-parse"]},"model-list":{requires:["array-extras","array-invoke","arraylist","base-build","escape","json-parse","model"]},"model-sync-rest":{requires:["model","io-base","json-stringify"]},node:{use:["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"]},"node-base":{requires:["event-base","node-core","dom-base"]},"node-core":{requires:["dom-core","selector"]},"node-deprecated":{requires:["node-base"]},"node-event-delegate":{requires:["node-base","event-delegate"]},"node-event-html5":{requires:["node-base"]},"node-event-simulate":{requires:["node-base","event-simulate","gesture-simulate"]},"node-flick":{requires:["classnamemanager","transition","event-flick","plugin"],skinnable:!0},"node-focusmanager":{requires:["attribute","node","plugin","node-event-simulate","event-key","event-focus"]},"node-load":{requires:["node-base","io-base"]},"node-menunav":{requires:["node","classnamemanager","plugin","node-focusmanager"],skinnable:!0},"node-pluginhost":{requires:["node-base","pluginhost"]},"node-screen":{requires:["dom-screen","node-base"]},"node-scroll-info":{requires:["base-build","dom-screen","event-resize","node-pluginhost","plugin"]},"node-style":{requires:["dom-style","node-base"]},oop:{requires:["yui-base"]},overlay:{requires:["widget","widget-stdmod","widget-position","widget-position-align","widget-stack","widget-position-constrain"],skinnable:!0},panel:{requires:["widget","widget-autohide","widget-buttons","widget-modality","widget-position","widget-position-align","widget-position-constrain","widget-stack","widget-stdmod"],skinnable:!0},parallel:{requires:["yui-base"]},pjax:{requires:["pjax-base","pjax-content"]},"pjax-base":{requires:["classnamemanager","node-event-delegate","router"]},"pjax-content":{requires:["io-base","node-base","router"]},"pjax-plugin":{requires:["node-pluginhost","pjax","plugin"]},plugin:{requires:["base-base"]},pluginhost:{use:["pluginhost-base","pluginhost-config"]},"pluginhost-base":{requires:["yui-base"]},"pluginhost-config":{requires:["pluginhost-base"]},profiler:{requires:["yui-base"]},querystring:{use:["querystring-parse","querystring-stringify"]},"querystring-parse":{requires:["yui-base","array-extras"]},"querystring-parse-simple":{requires:["yui-base"]},"querystring-stringify":{requires:["yui-base"]},"querystring-stringify-simple":{requires:["yui-base"]},"queue-promote":{requires:["yui-base"]},"range-slider":{requires:["slider-base","slider-value-range","clickable-rail"]},recordset:{use:["recordset-base","recordset-sort","recordset-filter","recordset-indexer"]},"recordset-base":{requires:["base","arraylist"]},"recordset-filter":{requires:["recordset-base","array-extras","plugin"]},"recordset-indexer":{requires:["recordset-base","plugin"]},"recordset-sort":{requires:["arraysort","recordset-base","plugin"]},resize:{use:["resize-base","resize-proxy","resize-constrain"]},"resize-base":{requires:["base","widget","event","oop","dd-drag","dd-delegate","dd-drop"],skinnable:!0},"resize-constrain":{requires:["plugin","resize-base"]},"resize-plugin":{optional:["resize-constrain"],requires:["resize-base","plugin"]},"resize-proxy":{requires:["plugin","resize-base"]},router:{optional:["querystring-parse"],requires:["array-extras","base-build","history"]},scrollview:{requires:["scrollview-base","scrollview-scrollbars"]},"scrollview-base":{requires:["widget","event-gestures","event-mousewheel","transition"],skinnable:!0},"scrollview-base-ie":{condition:{name:"scrollview-base-ie",trigger:"scrollview-base",ua:"ie"},requires:["scrollview-base"]},"scrollview-list":{requires:["plugin","classnamemanager"],skinnable:!0},"scrollview-paginator":{requires:["plugin","classnamemanager"]},"scrollview-scrollbars":{requires:["classnamemanager","transition","plugin"],skinnable:!0},selector:{requires:["selector-native"]},"selector-css2":{condition:{name:"selector-css2",test:function(e){var t=e.config.doc,n=t&&!("querySelectorAll"in t);return n},trigger:"selector"},requires:["selector-native"]},"selector-css3":{requires:["selector-native","selector-css2"]},"selector-native":{requires:["dom-base"]},"shim-plugin":{requires:["node-style","node-pluginhost"]},slider:{use:["slider-base","slider-value-range","clickable-rail","range-slider"]},"slider-base":{requires:["widget","dd-constrain","event-key"],skinnable:!0},"slider-value-range":{requires:["slider-base"]},sortable:{requires:["dd-delegate","dd-drop-plugin","dd-proxy"]},"sortable-scroll":{requires:["dd-scroll","sortable"]},stylesheet:{requires:["yui-base"]},substitute:{optional:["dump"],requires:["yui-base"]},swf:{requires:["event-custom","node","swfdetect","escape"]},swfdetect:{requires:["yui-base"]},tabview:{requires:["widget","widget-parent","widget-child","tabview-base","node-pluginhost","node-focusmanager"],skinnable:!0},"tabview-base":{requires:["node-event-delegate","classnamemanager","skin-sam-tabview"]},"tabview-plugin":{requires:["tabview-base"]},test:{requires:["event-simulate","event-custom","json-stringify"]},"test-console":{requires:["console-filters","test","array-extras"],skinnable:!0},text:{use:["text-accentfold","text-wordbreak"]},"text-accentfold":{requires:["array-extras","text-data-accentfold"]},"text-data-accentfold":{requires:["yui-base"]},"text-data-wordbreak":{requires:["yui-base"]},"text-wordbreak":{requires:["array-extras","text-data-wordbreak"]},transition:{requires:["node-style"]},"transition-timer":{condition:{name:"transition-timer",test:function(e){var t=e.config.doc,n=t?t.documentElement:null,r=!0;return n&&n.style&&(r=!("MozTransition"in n.style||"WebkitTransition"in n.style||"transition"in n.style)),r},trigger:"transition"},requires:["transition"]},uploader:{requires:["uploader-html5","uploader-flash"]},"uploader-deprecated":{requires:["event-custom","node","base","swf"]},"uploader-flash":{requires:["swf","widget","substitute","base","cssbutton","node","event-custom","file-flash","uploader-queue"]},"uploader-html5":{requires:["widget","node-event-simulate","substitute","file-html5","uploader-queue"]},"uploader-queue":{requires:["base"]},view:{requires:["base-build","node-event-delegate"]},"view-node-map":{requires:["view"]},widget:{use:["widget-base","widget-htmlparser","widget-skin","widget-uievents"]},"widget-anim":{requires:["anim-base","plugin","widget"]},"widget-autohide":{requires:["base-build","event-key","event-outside","widget"]},"widget-base":{requires:["attribute","base-base","base-pluginhost","classnamemanager","event-focus","node-base","node-style"],skinnable:!0},"widget-base-ie":{condition:{name:"widget-base-ie",trigger:"widget-base",ua:"ie"},requires:["widget-base"]},"widget-buttons":{requires:["button-plugin","cssbutton","widget-stdmod"]},"widget-child":{requires:["base-build","widget"]},"widget-htmlparser":{requires:["widget-base"]},"widget-locale":{requires:["widget-base"]},"widget-modality":{requires:["base-build","event-outside","widget"],skinnable:!0},"widget-parent":{requires:["arraylist","base-build","widget"]},"widget-position":{requires:["base-build","node-screen","widget"]},"widget-position-align":{requires:["widget-position"]},"widget-position-constrain":{requires:["widget-position"]},"widget-skin":{requires:["widget-base"]},"widget-stack":{requires:["base-build","widget"],skinnable:!0},"widget-stdmod":{requires:["base-build","widget"]},"widget-uievents":{requires:["node-event-delegate","widget-base"]},yql:{requires:["jsonp","jsonp-url"]},"yql-nodejs":{condition:{name:"yql-nodejs",trigger:"yql",ua:"nodejs",when:"after"}},"yql-winjs":{condition:{name:"yql-winjs",trigger:"yql",ua:"winjs",when:"after"}},yui:{},"yui-base":{},"yui-later":{requires:["yui-base"]},"yui-log":{requires:["yui-base"]},"yui-throttle":{requires:["yui-base"]}},YUI.Env[e.version].md5="a28e022ad022130f7a4fb4ac77a2f1df"},"3.7.3",{requires:["loader-base"]}),YUI.add("yui",function(e,t){},"3.7.3",{use:["yui-base","get","features","intl-base","yui-log","yui-later","loader-base","loader-rollup","loader-yui3"]});
diff --git a/long_list.cgi b/long_list.cgi
new file mode 100755
index 000000000..58bd255a3
--- /dev/null
+++ b/long_list.cgi
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Terry Weissman <terry@mozilla.org>
+# Gervase Markham <gerv@gerv.net>
+
+use strict;
+use lib qw(. lib);
+use Bugzilla;
+
+my $cgi = Bugzilla->cgi;
+
+# Convert comma/space separated elements into separate params
+my $buglist = $cgi->param('buglist') || $cgi->param('bug_id') || $cgi->param('id') || '';
+my @ids = split (/[\s,]+/, $buglist);
+
+my $ids = join('', map { $_ = "&id=" . $_ } @ids);
+
+print $cgi->redirect("show_bug.cgi?format=multiple$ids");
diff --git a/mod_perl.pl b/mod_perl.pl
index f3dae34c1..73ba4bd9e 100644
--- a/mod_perl.pl
+++ b/mod_perl.pl
@@ -59,9 +59,13 @@ Bugzilla::CGI->compile(qw(:cgi :push));
use Apache2::SizeLimit;
# This means that every httpd child will die after processing
-# a CGI if it is taking up more than 45MB of RAM all by itself,
+# a CGI if it is taking up more than 1600MB of RAM all by itself,
# not counting RAM it is sharing with the other httpd processes.
-Apache2::SizeLimit->set_max_unshared_size(45_000);
+if (Bugzilla->params->{'urlbase'} eq 'https://bugzilla.mozilla.org/') {
+ Apache2::SizeLimit->set_max_unshared_size(500_000);
+} else {
+ Apache2::SizeLimit->set_max_unshared_size(250_000);
+}
my $cgi_path = Bugzilla::Constants::bz_locations()->{'cgi_path'};
@@ -80,7 +84,7 @@ PerlChildInitHandler "sub { Bugzilla::RNG::srand(); srand(); }"
PerlResponseHandler Bugzilla::ModPerl::ResponseHandler
PerlCleanupHandler Apache2::SizeLimit Bugzilla::ModPerl::CleanupHandler
PerlOptions +ParseHeaders
- Options +ExecCGI
+ Options +ExecCGI +FollowSymLinks
AllowOverride Limit FileInfo Indexes
DirectoryIndex index.cgi index.html
</Directory>
diff --git a/post_bug.cgi b/post_bug.cgi
index c0878b0da..af8c2cd2e 100755
--- a/post_bug.cgi
+++ b/post_bug.cgi
@@ -60,6 +60,12 @@ unless ($cgi->param()) {
exit;
}
+# BMO: Don't allow updating of bugs if disabled
+if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+}
+
# Detect if the user already used the same form to submit a bug
my $token = trim($cgi->param('token'));
check_token_data($token, 'create_bug', 'index.cgi');
diff --git a/process_bug.cgi b/process_bug.cgi
index 9272dec60..1f613982d 100755
--- a/process_bug.cgi
+++ b/process_bug.cgi
@@ -93,6 +93,12 @@ sub should_set {
# Begin Data/Security Validation
######################################################################
+# BMO: Don't allow updating of bugs if disabled
+if (Bugzilla->params->{disable_bug_updates}) {
+ ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+ 'Bug updates are currently disabled.');
+}
+
# Create a list of objects for all bugs being modified in this request.
my @bug_objects;
if (defined $cgi->param('id')) {
@@ -147,23 +153,43 @@ if (defined $cgi->param('delta_ts'))
Bugzilla::Bug::GetBugActivity($first_bug->id, undef,
scalar $cgi->param('delta_ts'));
- $vars->{'title_tag'} = "mid_air";
-
ThrowCodeError('undefined_field', { field => 'longdesclength' })
if !defined $cgi->param('longdesclength');
- $vars->{'start_at'} = $cgi->param('longdesclength');
+ my $start_at = $cgi->param('longdesclength');
+
# Always sort midair collision comments oldest to newest,
# regardless of the user's personal preference.
- $vars->{'comments'} = $first_bug->comments({ order => "oldest_to_newest" });
- $vars->{'bug'} = $first_bug;
+ my $comments = $first_bug->comments({ order => "oldest_to_newest" });
# The token contains the old delta_ts. We need a new one.
$cgi->param('token', issue_hash_token([$first_bug->id, $first_bug->delta_ts]));
- # Warn the user about the mid-air collision and ask them what to do.
- $template->process("bug/process/midair.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
- exit;
+
+ # Show midair if previous changes made other than CC
+ # and/or one or more comments were made
+ my $do_midair = scalar @$comments > $start_at ? 1 : 0;
+
+ if (!$do_midair) {
+ foreach my $operation (@{ $vars->{'operations'} }) {
+ foreach my $change (@{ $operation->{'changes'} }) {
+ $do_midair = 1 if $change->{'fieldname'} ne 'cc';
+ last;
+ }
+ last if $do_midair;
+ }
+ }
+
+ if ($do_midair) {
+ $vars->{'title_tag'} = "mid_air";
+ $vars->{'start_at'} = $start_at;
+ $vars->{'comments'} = $comments;
+ $vars->{'bug'} = $first_bug;
+
+ # Warn the user about the mid-air collision and ask them what to do.
+ $template->process("bug/process/midair.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
}
}
@@ -230,9 +256,9 @@ my @set_fields = qw(op_sys rep_platform priority bug_severity
bug_file_loc status_whiteboard short_desc
deadline remaining_time estimated_time
work_time set_default_assignee set_default_qa_contact
- cclist_accessible reporter_accessible
+ cclist_accessible reporter_accessible
product confirm_product_change
- bug_status resolution dup_id);
+ bug_status resolution dup_id bug_ignored);
push(@set_fields, 'assigned_to') if !$cgi->param('set_default_assignee');
push(@set_fields, 'qa_contact') if !$cgi->param('set_default_qa_contact');
my %field_translation = (
diff --git a/quips.cgi b/quips.cgi
index 74c0047a1..14126e43c 100755
--- a/quips.cgi
+++ b/quips.cgi
@@ -78,6 +78,7 @@ if ($action eq "add") {
check_hash_token($token, ['create-quips']);
# Add the quip
+ # Upstreaming: https://bugzilla.mozilla.org/show_bug.cgi?id=621879
my $approved = (Bugzilla->params->{'quip_list_entry_control'} eq "open")
|| $user->in_group('bz_quip_moderators') || 0;
my $comment = $cgi->param("quip");
diff --git a/report.cgi b/report.cgi
index 7bff62be9..decbaeeb2 100755
--- a/report.cgi
+++ b/report.cgi
@@ -131,13 +131,12 @@ my $search = new Bugzilla::Search(
params => scalar $params->Vars,
allow_unlimited => 1,
);
-my $query = $search->sql;
$::SIG{TERM} = 'DEFAULT';
$::SIG{PIPE} = 'DEFAULT';
-my $dbh = Bugzilla->switch_to_shadow_db();
-my $results = $dbh->selectall_arrayref($query);
+Bugzilla->switch_to_shadow_db();
+my ($results, $extra_data) = $search->data;
# We have a hash of hashes for the data itself, and a hash to hold the
# row/col/table names.
@@ -224,8 +223,7 @@ if ($width && $formatparam eq "bar") {
$vars->{'width'} = $width if $width;
$vars->{'height'} = $height if $height;
-
-$vars->{'query'} = $query;
+$vars->{'queries'} = $extra_data;
if ($cgi->param('debug')
&& Bugzilla->params->{debug_group}
diff --git a/request.cgi b/request.cgi
index 16d7662e8..5ac95f240 100755
--- a/request.cgi
+++ b/request.cgi
@@ -114,7 +114,11 @@ sub queue {
flags.attach_id, attachments.description,
requesters.realname, requesters.login_name,
requestees.realname, requestees.login_name, COUNT(privs.group_id),
- " . $dbh->sql_date_format('flags.modification_date', '%Y.%m.%d %H:%i') .
+ " . $dbh->sql_date_format('flags.modification_date', '%Y.%m.%d %H:%i') . ",
+ attachments.ispatch,
+ bugs.bug_status,
+ bugs.priority,
+ bugs.bug_severity " .
# Use the flags and flagtypes tables for information about the flags,
# the bugs and attachments tables for target info, the profiles tables
# for setter and requestee info, the products/components tables
@@ -175,16 +179,18 @@ sub queue {
# column will always be the same.
my @excluded_columns = ();
+ my $do_union = $cgi->param('do_union');
+
# Filter requests by status: "pending", "granted", "denied", "all"
# (which means any), or "fulfilled" (which means "granted" or "denied").
if ($status) {
if ($status eq "+-") {
push(@criteria, "flags.status IN ('+', '-')");
- push(@excluded_columns, 'status') unless $cgi->param('do_union');
+ push(@excluded_columns, 'status') unless $do_union;
}
elsif ($status ne "all") {
push(@criteria, "flags.status = '$status'");
- push(@excluded_columns, 'status') unless $cgi->param('do_union');
+ push(@excluded_columns, 'status') unless $do_union;
}
}
@@ -193,7 +199,7 @@ sub queue {
my $requester = $dbh->quote($cgi->param('requester'));
trick_taint($requester); # Quoted above
push(@criteria, $dbh->sql_istrcmp('requesters.login_name', $requester));
- push(@excluded_columns, 'requester') unless $cgi->param('do_union');
+ push(@excluded_columns, 'requester') unless $do_union;
}
if (defined $cgi->param('requestee') && $cgi->param('requestee') ne "") {
if ($cgi->param('requestee') ne "-") {
@@ -203,19 +209,19 @@ sub queue {
$requestee));
}
else { push(@criteria, "flags.requestee_id IS NULL") }
- push(@excluded_columns, 'requestee') unless $cgi->param('do_union');
+ push(@excluded_columns, 'requestee') unless $do_union;
}
# Filter results by exact product or component.
if (defined $cgi->param('product') && $cgi->param('product') ne "") {
my $product = Bugzilla::Product->check(scalar $cgi->param('product'));
push(@criteria, "bugs.product_id = " . $product->id);
- push(@excluded_columns, 'product') unless $cgi->param('do_union');
+ push(@excluded_columns, 'product') unless $do_union;
if (defined $cgi->param('component') && $cgi->param('component') ne "") {
my $component = Bugzilla::Component->check({ product => $product,
name => scalar $cgi->param('component') });
push(@criteria, "bugs.component_id = " . $component->id);
- push(@excluded_columns, 'component') unless $cgi->param('do_union');
+ push(@excluded_columns, 'component') unless $do_union;
}
}
@@ -233,13 +239,12 @@ sub queue {
my $quoted_form_type = $dbh->quote($form_type);
trick_taint($quoted_form_type); # Already SQL quoted
push(@criteria, "flagtypes.name = " . $quoted_form_type);
- push(@excluded_columns, 'type') unless $cgi->param('do_union');
+ push(@excluded_columns, 'type') unless $do_union;
}
- # Add the criteria to the query. We do an intersection by default
- # but do a union if the "do_union" URL parameter (for which there is no UI
- # because it's an advanced feature that people won't usually want) is true.
- my $and_or = $cgi->param('do_union') ? " OR " : " AND ";
+ # Add the criteria to the query. Do a union if OR is selected.
+ # Otherwise do an intersection.
+ my $and_or = $do_union ? ' OR ' : ' AND ';
$query .= " AND (" . join($and_or, @criteria) . ") " if scalar(@criteria);
# Group the records by flag ID so we don't get multiple rows of data
@@ -250,9 +255,9 @@ sub queue {
products.name, components.name, flags.attach_id,
attachments.description, requesters.realname,
requesters.login_name, requestees.realname,
- requestees.login_name, flags.modification_date,
+ requestees.login_name, flags.modification_date, attachments.ispatch
cclist_accessible, bugs.reporter, bugs.reporter_accessible,
- bugs.assigned_to');
+ bugs.assigned_to, attachments.ispatch');
# Group the records, in other words order them by the group column
# so the loop in the display template can break them up into separate
@@ -278,7 +283,7 @@ sub queue {
# Pass the query to the template for use when debugging this script.
$vars->{'query'} = $query;
$vars->{'debug'} = $cgi->param('debug') ? 1 : 0;
-
+
my $results = $dbh->selectall_arrayref($query);
my @requests = ();
foreach my $result (@$results) {
@@ -295,7 +300,11 @@ sub queue {
'requester' => ($data[9] ? "$data[9] <$data[10]>" : $data[10]) ,
'requestee' => ($data[11] ? "$data[11] <$data[12]>" : $data[12]) ,
'restricted' => $data[13] ? 1 : 0,
- 'created' => $data[14]
+ 'created' => $data[14],
+ 'ispatch' => $data[15],
+ 'bug_status' => $data[16],
+ 'priority' => $data[17],
+ 'bug_severity' => $data[18],
};
push(@requests, $request);
}
diff --git a/robots.txt b/robots.txt
index 0f823cb24..841ebc77e 100644
--- a/robots.txt
+++ b/robots.txt
@@ -1,3 +1,16 @@
+User-agent: Browsershots
+Disallow:
+
User-agent: *
-Allow: /index.cgi
Disallow: /
+Allow: /*index.cgi
+Allow: /*page.cgi
+Allow: /*show_bug.cgi
+Allow: /*describecomponents.cgi
+Allow: /*describekeywords.cgi
+Allow: /*data/SiteMapIndex/sitemap*.xml.gz
+Disallow: /*show_bug.cgi*ctype=*
+Disallow: /*show_bug.cgi*format=multiple*
+Disallow: /*page.cgi*id=voting*
+Disallow: /*page.cgi*id=productdashboard*
+Sitemap: http://bugzilla.mozilla.org/page.cgi?id=sitemap/sitemap.xml
diff --git a/sanitycheck.cgi b/sanitycheck.cgi
index 7d530ea4b..36751d821 100755
--- a/sanitycheck.cgi
+++ b/sanitycheck.cgi
@@ -225,7 +225,7 @@ if ($cgi->param('repair_bugs_fulltext')) {
WHERE bugs_fulltext.bug_id IS NULL');
foreach my $bugid (@$bug_ids) {
- Bugzilla::Bug->new($bugid)->_sync_fulltext('new_bug');
+ Bugzilla::Bug->new($bugid)->_sync_fulltext( new_bug => 1 );
}
Status('bugs_fulltext_fixed', {bug_count => scalar(@$bug_ids)});
diff --git a/search_plugin.cgi b/search_plugin.cgi
index 4dfe8fa9f..b50467911 100755
--- a/search_plugin.cgi
+++ b/search_plugin.cgi
@@ -31,13 +31,5 @@ my $vars = {};
# Return the appropriate HTTP response headers.
print $cgi->header('application/xml');
-# Get the contents of favicon.ico
-my $filename = bz_locations()->{'libpath'} . "/images/favicon.ico";
-if (open(IN, $filename)) {
- local $/;
- binmode IN;
- $vars->{'favicon'} = <IN>;
- close IN;
-}
$template->process("search/search-plugin.xml.tmpl", $vars)
|| ThrowTemplateError($template->error());
diff --git a/show_bug.cgi b/show_bug.cgi
index a2bf57ada..332d5fcbd 100755
--- a/show_bug.cgi
+++ b/show_bug.cgi
@@ -61,7 +61,7 @@ Bugzilla->switch_to_shadow_db unless $user->id;
if ($single) {
my $id = $cgi->param('id');
- push @bugs, Bugzilla::Bug->check($id);
+ push @bugs, Bugzilla::Bug->check({ id => $id, cache => 1 });
if (defined $cgi->param('mark')) {
foreach my $range (split ',', $cgi->param('mark')) {
if ($range =~ /^(\d+)-(\d+)$/) {
@@ -77,8 +77,8 @@ if ($single) {
foreach my $id ($cgi->param('id')) {
# Be kind enough and accept URLs of the form: id=1,2,3.
my @ids = split(/,/, $id);
- foreach (@ids) {
- my $bug = new Bugzilla::Bug($_);
+ foreach my $bug_id (@ids) {
+ my $bug = new Bugzilla::Bug({ id => $bug_id, cache => 1 });
# This is basically a backwards-compatibility hack from when
# Bugzilla::Bug->new used to set 'NotPermitted' if you couldn't
# see the bug.
diff --git a/showattachment.cgi b/showattachment.cgi
new file mode 100755
index 000000000..e90a01533
--- /dev/null
+++ b/showattachment.cgi
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Terry Weissman <terry@mozilla.org>
+# Jacob Steenhagen <jake@bugzilla.org>
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Util;
+
+my $cgi = Bugzilla->cgi;
+
+my $id = $cgi->param('attach_id');
+detaint_natural($id) if defined $id;
+$id ||= "";
+
+print $cgi->redirect(-location=>"attachment.cgi?id=$id",
+ -status=>'301 Permanent Redirect');
+
+exit;
diff --git a/showdependencygraph.cgi b/showdependencygraph.cgi
index 71eaa9183..28b113460 100755
--- a/showdependencygraph.cgi
+++ b/showdependencygraph.cgi
@@ -44,7 +44,8 @@ my $vars = {};
# performance.
my $dbh = Bugzilla->switch_to_shadow_db();
-local our (%seen, %edgesdone, %bugtitles);
+our (%seen, %edgesdone, %bugtitles);
+our $bug_count = 0;
# CreateImagemap: This sub grabs a local filename as a parameter, reads the
# dot-generated image map datafile residing in that file and turns it into
@@ -91,6 +92,7 @@ sub AddLink {
if (!exists $edgesdone{$key}) {
$edgesdone{$key} = 1;
print $fh "$dependson -> $blocked\n";
+ $bug_count++;
$seen{$blocked} = 1;
$seen{$dependson} = 1;
}
@@ -123,10 +125,10 @@ chmod Bugzilla::Install::Filesystem::CGI_WRITE, $filename
my $urlbase = correct_urlbase();
print $fh "digraph G {";
-print $fh qq{
+print $fh qq(
graph [URL="${urlbase}query.cgi", rankdir=$rankdir]
node [URL="${urlbase}show_bug.cgi?id=\\N", style=filled, color=lightgrey]
-};
+);
my %baselist;
@@ -236,6 +238,11 @@ foreach my $k (keys(%seen)) {
print $fh "}\n";
close $fh;
+if ($bug_count > MAX_WEBDOT_BUGS) {
+ unlink($filename);
+ ThrowUserError("webdot_too_large");
+}
+
my $webdotbase = Bugzilla->params->{'webdotbase'};
if ($webdotbase =~ /^https?:/) {
@@ -311,7 +318,8 @@ foreach my $f (@files)
# symlinks), this can't escape to delete anything it shouldn't
# (unless someone moves the location of $webdotdir, of course)
trick_taint($f);
- if (file_mod_time($f) < $since) {
+ my $mtime = file_mod_time($f);
+ if ($mtime && $mtime < $since) {
unlink $f;
}
}
diff --git a/skins/contrib/Dusk-Helvetica/buglist.css b/skins/contrib/Dusk-Helvetica/buglist.css
new file mode 100644
index 000000000..2e14368b1
--- /dev/null
+++ b/skins/contrib/Dusk-Helvetica/buglist.css
@@ -0,0 +1,24 @@
+/* The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is Mike Schrag.
+ * Portions created by Marc Schumann are Copyright (c) 2007 Mike Schrag.
+ * All rights reserved.
+ *
+ * Contributor(s): Mike Schrag <mschrag@pobox.com>
+ * Byron Jones <bugzilla@glob.com.au>
+ * Marc Schumann <wurblzap@gmail.com>
+ */
+
+tr.bz_bugitem:hover {
+ background-color: #ccccff;
+}
diff --git a/skins/contrib/Dusk-Helvetica/global.css b/skins/contrib/Dusk-Helvetica/global.css
new file mode 100644
index 000000000..8478c1a88
--- /dev/null
+++ b/skins/contrib/Dusk-Helvetica/global.css
@@ -0,0 +1,263 @@
+/* The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is Mike Schrag.
+ * Portions created by Marc Schumann are Copyright (c) 2007 Mike Schrag.
+ * All rights reserved.
+ *
+ * Contributor(s): Mike Schrag <mschrag@pobox.com>
+ * Byron Jones <bugzilla@glob.com.au>
+ * Marc Schumann <wurblzap@gmail.com>
+ * Frédéric Buclin <LpSolit@gmail.com>
+ */
+
+body {
+ background: #c8c8c8;
+ font-family: "Helvetica Neue", "Nimbus Sans L", Arial, sans-serif;
+ padding-left: 1em;
+ padding-right: 1em;
+}
+
+body, td, th, input {
+ font-family: "Helvetica Neue", "Nimbus Sans L", Arial, sans-serif;
+}
+
+/* page title */
+
+#titles {
+ -moz-border-radius-topleft: 5px;
+ -moz-border-radius-topright: 5px;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+}
+
+#header .links, #footer {
+ background-color: #929bb1;
+ color: #ddd;
+}
+
+#header {
+ -moz-border-radius-bottomleft: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
+ border: none;
+}
+
+#header a, #footer a {
+ color: white;
+ text-decoration: none;
+}
+#header a:hover, #footer a:hover {
+ text-decoration: underline;
+}
+
+/* body */
+
+#bugzilla-body {
+ background: #f0f0f0;
+ color: black;
+ border: 1px solid #747e93;
+ padding: 10px;
+ font-size: 10pt;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+a {
+ color: #6070cf;
+}
+a:hover {
+ color: #8090ef;
+}
+
+hr {
+ border-color: #969696;
+ border-style: dashed;
+ border-width: 1px;
+ margin-top: 10px;
+}
+
+/* edit */
+
+#bugzilla-body th {
+ font-weight: bold;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+#bug-form td {
+ padding-top: 2px;
+}
+
+/* attachments */
+
+#attachment-list {
+ border: 2px solid #c8c8ba;
+ font-size: 9pt;
+}
+
+#attachment-list th {
+ background-color: #e6e6d8;
+ border: none;
+ border-bottom: 1px solid #c8c8ba;
+ text-align: left;
+}
+
+#attachment-list th a {
+ color: #646456;
+}
+
+#attachment-list td {
+ border: none;
+}
+
+#attachment-list-actions td {
+ border-top: 1px solid #c8c8ba;
+}
+
+/************/
+/* Comments */
+/************/
+
+#comments th {
+ font-size: 9pt;
+ font-weight: bold;
+ padding-top: 5px;
+ padding-right: 5px;
+ padding-bottom: 10px;
+ text-align: right;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+#comments td {
+ padding-top: 2px;
+}
+
+.reply-button a {
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.bz_comment {
+ background-color: #e8e8e8;
+ margin: 1px 1px 10px 1px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #c8c8ba;
+ padding: 5px;
+ font-size: 9pt;
+}
+
+.bz_comment_head, .bz_first_comment_head {
+ margin: 0; padding: 0;
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.bz_comment_user {
+ margin-left: 0;
+}
+
+.bz_comment.bz_private {
+ background-color: #f0e8e8;
+ border-color: #f8c8ba;
+}
+
+.comment_rule {
+ display: none;
+}
+
+/* footer */
+
+#footer {
+ border: 1px solid #747e93;
+ width: 100%;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#footer #links-actions,
+#footer #links-edit,
+#footer #links-saved,
+#footer #links-special {
+ margin-top: 2ex;
+}
+
+#footer .links {
+ border-spacing: 30px;
+ margin-bottom: 2ex;
+}
+
+.separator {
+ color: #cccccc;
+}
+
+/* tabs */
+
+.tabbed .tabbody {
+ background: #f8f8f8;
+ padding: 1em;
+ border-style: solid;
+ border-color: #000000;
+ border-width: 0 3px 3px 1px;
+}
+
+.tabs {
+ margin: 0;
+ padding: 0;
+ border-collapse: collapse;
+}
+
+.tabs td {
+ background: #c8c8c8;
+ border-width: 1px;
+}
+
+.tabs td.selected {
+ background: #f8f8f8;
+ border-width: 1px 3px 0 1px;
+}
+
+.tabs td.spacer {
+ background: transparent;
+ border-top: none;
+ border-left: none;
+ border-right: none;
+}
+
+/* other */
+
+.bz_row_odd {
+ background-color: #f0f0f0;
+}
+
+/* Rules specific for printing */
+@media print {
+ #header,
+ #footer,
+ .navigation {
+ display: none;
+ }
+
+ body {
+ background-image: none;
+ background-color: #ffffff;
+ }
+
+ #bugzilla-body {
+ border: none;
+ margin: 0;
+ padding: 0;
+ }
+}
diff --git a/skins/contrib/Dusk-Helvetica/index.css b/skins/contrib/Dusk-Helvetica/index.css
new file mode 100644
index 000000000..c9c2d1705
--- /dev/null
+++ b/skins/contrib/Dusk-Helvetica/index.css
@@ -0,0 +1,9 @@
+/*
+ * Custom rules for index.css.
+ * The rules you put here override rules in that stylesheet.
+ */
+
+ div#page-index .outro
+ {
+ clear:both;
+ }
diff --git a/skins/contrib/Dusk-Segoe/buglist.css b/skins/contrib/Dusk-Segoe/buglist.css
new file mode 100644
index 000000000..2e14368b1
--- /dev/null
+++ b/skins/contrib/Dusk-Segoe/buglist.css
@@ -0,0 +1,24 @@
+/* The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is Mike Schrag.
+ * Portions created by Marc Schumann are Copyright (c) 2007 Mike Schrag.
+ * All rights reserved.
+ *
+ * Contributor(s): Mike Schrag <mschrag@pobox.com>
+ * Byron Jones <bugzilla@glob.com.au>
+ * Marc Schumann <wurblzap@gmail.com>
+ */
+
+tr.bz_bugitem:hover {
+ background-color: #ccccff;
+}
diff --git a/skins/contrib/Dusk-Segoe/global.css b/skins/contrib/Dusk-Segoe/global.css
new file mode 100644
index 000000000..f431aceba
--- /dev/null
+++ b/skins/contrib/Dusk-Segoe/global.css
@@ -0,0 +1,263 @@
+/* The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is Mike Schrag.
+ * Portions created by Marc Schumann are Copyright (c) 2007 Mike Schrag.
+ * All rights reserved.
+ *
+ * Contributor(s): Mike Schrag <mschrag@pobox.com>
+ * Byron Jones <bugzilla@glob.com.au>
+ * Marc Schumann <wurblzap@gmail.com>
+ * Frédéric Buclin <LpSolit@gmail.com>
+ */
+
+body {
+ background: #c8c8c8;
+ font-family: Segoe, "Segoe UI", "Helvetica Neue", Verdana, sans-serif;
+ padding-left: 1em;
+ padding-right: 1em;
+}
+
+body, td, th, input {
+ font-family: Segoe, "Segoe UI", "Helvetica Neue", Verdana, sans-serif;
+}
+
+/* page title */
+
+#titles {
+ -moz-border-radius-topleft: 5px;
+ -moz-border-radius-topright: 5px;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+}
+
+#header .links, #footer {
+ background-color: #929bb1;
+ color: #ddd;
+}
+
+#header {
+ -moz-border-radius-bottomleft: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
+ border: none;
+}
+
+#header a, #footer a {
+ color: white;
+ text-decoration: none;
+}
+#header a:hover, #footer a:hover {
+ text-decoration: underline;
+}
+
+/* body */
+
+#bugzilla-body {
+ background: #f0f0f0;
+ color: black;
+ border: 1px solid #747e93;
+ padding: 10px;
+ font-size: 10pt;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+a {
+ color: #6070cf;
+}
+a:hover {
+ color: #8090ef;
+}
+
+hr {
+ border-color: #969696;
+ border-style: dashed;
+ border-width: 1px;
+ margin-top: 10px;
+}
+
+/* edit */
+
+#bugzilla-body th {
+ font-weight: bold;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+#bug-form td {
+ padding-top: 2px;
+}
+
+/* attachments */
+
+#attachment-list {
+ border: 2px solid #c8c8ba;
+ font-size: 9pt;
+}
+
+#attachment-list th {
+ background-color: #e6e6d8;
+ border: none;
+ border-bottom: 1px solid #c8c8ba;
+ text-align: left;
+}
+
+#attachment-list th a {
+ color: #646456;
+}
+
+#attachment-list td {
+ border: none;
+}
+
+#attachment-list-actions td {
+ border-top: 1px solid #c8c8ba;
+}
+
+/************/
+/* Comments */
+/************/
+
+#comments th {
+ font-size: 9pt;
+ font-weight: bold;
+ padding-top: 5px;
+ padding-right: 5px;
+ padding-bottom: 10px;
+ text-align: right;
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+#comments td {
+ padding-top: 2px;
+}
+
+.reply-button a {
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.bz_comment {
+ background-color: #e8e8e8;
+ margin: 1px 1px 10px 1px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #c8c8ba;
+ padding: 5px;
+ font-size: 9pt;
+}
+
+.bz_comment_head, .bz_first_comment_head {
+ margin: 0; padding: 0;
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.bz_comment_user {
+ margin-left: 0;
+}
+
+.bz_comment.bz_private {
+ background-color: #f0e8e8;
+ border-color: #f8c8ba;
+}
+
+.comment_rule {
+ display: none;
+}
+
+/* footer */
+
+#footer {
+ border: 1px solid #747e93;
+ width: 100%;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#footer #links-actions,
+#footer #links-edit,
+#footer #links-saved,
+#footer #links-special {
+ margin-top: 2ex;
+}
+
+#footer .links {
+ border-spacing: 30px;
+ margin-bottom: 2ex;
+}
+
+.separator {
+ color: #cccccc;
+}
+
+/* tabs */
+
+.tabbed .tabbody {
+ background: #f8f8f8;
+ padding: 1em;
+ border-style: solid;
+ border-color: #000000;
+ border-width: 0 3px 3px 1px;
+}
+
+.tabs {
+ margin: 0;
+ padding: 0;
+ border-collapse: collapse;
+}
+
+.tabs td {
+ background: #c8c8c8;
+ border-width: 1px;
+}
+
+.tabs td.selected {
+ background: #f8f8f8;
+ border-width: 1px 3px 0 1px;
+}
+
+.tabs td.spacer {
+ background: transparent;
+ border-top: none;
+ border-left: none;
+ border-right: none;
+}
+
+/* other */
+
+.bz_row_odd {
+ background-color: #f0f0f0;
+}
+
+/* Rules specific for printing */
+@media print {
+ #header,
+ #footer,
+ .navigation {
+ display: none;
+ }
+
+ body {
+ background-image: none;
+ background-color: #ffffff;
+ }
+
+ #bugzilla-body {
+ border: none;
+ margin: 0;
+ padding: 0;
+ }
+}
diff --git a/skins/contrib/Dusk-Segoe/index.css b/skins/contrib/Dusk-Segoe/index.css
new file mode 100644
index 000000000..c9c2d1705
--- /dev/null
+++ b/skins/contrib/Dusk-Segoe/index.css
@@ -0,0 +1,9 @@
+/*
+ * Custom rules for index.css.
+ * The rules you put here override rules in that stylesheet.
+ */
+
+ div#page-index .outro
+ {
+ clear:both;
+ }
diff --git a/skins/contrib/Dusk-Segoe/show_bug.css b/skins/contrib/Dusk-Segoe/show_bug.css
new file mode 100644
index 000000000..92e52d02e
--- /dev/null
+++ b/skins/contrib/Dusk-Segoe/show_bug.css
@@ -0,0 +1,3 @@
+.bz_comment {
+ font-size: small;
+}
diff --git a/skins/contrib/Dusk/global.css b/skins/contrib/Dusk/global.css
index 63375672b..33f28965c 100644
--- a/skins/contrib/Dusk/global.css
+++ b/skins/contrib/Dusk/global.css
@@ -22,11 +22,15 @@
body {
background: #c8c8c8;
- font-family: Helvetica, Arial, Geneva;
+ font-family: Verdana, sans-serif;
padding-left: 1em;
padding-right: 1em;
}
+body, td, th, input {
+ font-family: Verdana, sans-serif;
+}
+
/* page title */
#titles {
diff --git a/skins/contrib/Mozilla/bugzilla-magnifier.png b/skins/contrib/Mozilla/bugzilla-magnifier.png
new file mode 100644
index 000000000..b859b1668
--- /dev/null
+++ b/skins/contrib/Mozilla/bugzilla-magnifier.png
Binary files differ
diff --git a/skins/contrib/Mozilla/bugzilla-papericon.png b/skins/contrib/Mozilla/bugzilla-papericon.png
new file mode 100644
index 000000000..677567929
--- /dev/null
+++ b/skins/contrib/Mozilla/bugzilla-papericon.png
Binary files differ
diff --git a/skins/contrib/Mozilla/bugzilla-person-alternate.png b/skins/contrib/Mozilla/bugzilla-person-alternate.png
new file mode 100644
index 000000000..a9e9ff213
--- /dev/null
+++ b/skins/contrib/Mozilla/bugzilla-person-alternate.png
Binary files differ
diff --git a/skins/contrib/Mozilla/bugzilla-person.png b/skins/contrib/Mozilla/bugzilla-person.png
new file mode 100644
index 000000000..62351c265
--- /dev/null
+++ b/skins/contrib/Mozilla/bugzilla-person.png
Binary files differ
diff --git a/skins/contrib/Mozilla/bugzilla-questionmark2.png b/skins/contrib/Mozilla/bugzilla-questionmark2.png
new file mode 100644
index 000000000..441d07f93
--- /dev/null
+++ b/skins/contrib/Mozilla/bugzilla-questionmark2.png
Binary files differ
diff --git a/skins/contrib/Mozilla/dropdown.png b/skins/contrib/Mozilla/dropdown.png
new file mode 100644
index 000000000..e01e5e51d
--- /dev/null
+++ b/skins/contrib/Mozilla/dropdown.png
Binary files differ
diff --git a/skins/contrib/Mozilla/footer-mozilla.png b/skins/contrib/Mozilla/footer-mozilla.png
new file mode 100644
index 000000000..593c10308
--- /dev/null
+++ b/skins/contrib/Mozilla/footer-mozilla.png
Binary files differ
diff --git a/skins/contrib/Mozilla/global.css b/skins/contrib/Mozilla/global.css
new file mode 100644
index 000000000..4275fd728
--- /dev/null
+++ b/skins/contrib/Mozilla/global.css
@@ -0,0 +1,666 @@
+@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700|Droid+Sans+Mono);
+
+body {
+ background: #f6f4ec;
+ background-image: url(noise.png), -moz-linear-gradient(#d7d3c8, #f6f4ec 400px);
+ background-image: url(noise.png), -webkit-linear-gradient(#d7d3c8, #f6f4ec 400px);
+ background-image: url(noise.png), linear-gradient(#d7d3c8, #f6f4ec 400px);
+ color: #404040;
+ min-width: 990px;
+}
+
+body, td, th, input {
+ font-family: "Open Sans", "Helvetica Neue", Arial, Helvetica, sans-serif;
+}
+
+a, #header a, #header a:visited, #footer a, #footer a:visited {
+ color: #0095dd;
+}
+
+a:hover, #header a:hover, #footer a:hover {
+ color: #00539f;
+}
+
+textarea, input[type=text], .text_input {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
+ background: -moz-linear-gradient(#fafafa, #fff);
+ background: -webkit-linear-gradient(#fafafa, #fff);
+ background: linear-gradient(#fafafa, #fff);
+ padding: 5px;
+}
+
+hr {
+ display: none;
+}
+
+#header {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ background: -moz-linear-gradient(#e5e3dc, #ecebe5);
+ background: -webkit-linear-gradient(#e5e3dc, #ecebe5);
+ background: linear-gradient(#e5e3dc, #ecebe5);
+ border-radius: 0;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ border-top: 3px solid rgb(104, 104, 104);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ margin: -15px;
+ position: fixed;
+ width: 100%;
+ z-index: 2;
+ color: transparent;
+}
+
+#header .subheader {
+ text-align: left;
+ padding-left: 10px;
+}
+
+#header .wrapper {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ margin: 0px auto;
+ width: 99%;
+}
+
+#header .wrapper:after {
+ clear: both;
+ content: ".";
+ display: block;
+ height: 0;
+ visibility: hidden;
+}
+
+#titles {
+ width: 100%;
+ background-color: transparent;
+ padding: 0 1em 0 1em;
+}
+
+#titles #information {
+ text-align: left;
+ padding-left: 2em;
+}
+
+#titles #title {
+ width: 150px;
+ font-size: 120%;
+}
+
+#titles #tab {
+ width: 100px;
+}
+
+#titles #login {
+ text-align: right;
+ padding-right: 2em;
+ color: #404040;
+}
+
+#header .links {
+ background: transparent;
+ border: none;
+ border-radius: 0;
+ color: #404040;
+ position: relative;
+ margin-top: -15px;
+ width: 50%;
+}
+
+#header .links {
+ width: auto;
+}
+
+.login-links ul {
+}
+
+.login-links li {
+ display: inline;
+}
+
+.links a {
+ margin: 0 10px 0 10px;
+}
+
+.links .home {
+ font-weight: bold;
+}
+
+.links .separator {
+ display: none;
+}
+
+#quicksearch_top, #quicksearch_main {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ background: url(search.png) 5px center no-repeat, -moz-linear-gradient(#fafafa, #fff);
+ background: url(search.png) 5px center no-repeat, -webkit-linear-gradient(#fafafa, #fff);
+ background: url(search.png) 5px center no-repeat, linear-gradient(#fafafa, #fff);
+ padding-left: 26px;
+ width: 200px;
+}
+
+#footer .links .form {
+ display: none;
+}
+
+#header .form a {
+ margin: 0;
+}
+
+.links .dropdown {
+ background: rgba(0, 0, 0, 0.05);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 3px;
+ display: inline-block;
+ padding: 4px 8px;
+ position: relative;
+}
+
+.links .dropdown .anchor {
+ background-image: url(dropdown.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+ display: inline-block;
+ min-width: 110px;
+ padding-right: 15px;
+}
+
+.links .dropdown ul {
+ background: #fafafa;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0 0 5px 5px;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ display: none;
+ padding: 4px;
+ position: absolute;
+ right: -1px;
+ top: 26px;
+ z-index: 2;
+ text-align: left;
+}
+
+.links .dropdown:hover ul {
+ display: block;
+}
+
+.links .dropdown li {
+ display: block;
+}
+
+.links .dropdown:hover {
+ border-bottom-right-radius: 0;
+}
+
+.links .dropdown li {
+ display: block;
+}
+
+#bugzilla-body {
+ background: none;
+ border: none;
+ color: #404040;
+ margin: 80px auto 15px;
+ padding: 0;
+ width: 99%;
+}
+
+/* Home */
+
+#page-index {
+ max-width: none;
+}
+
+#page-index td:first-child {
+ text-align: center;
+}
+
+#quicksearch_links {
+ margin-top: 10px;
+}
+
+/* Bugs */
+
+.navigation {
+ background: rgba(255, 255, 255, 0.3);
+ padding: 5px 10px;
+}
+
+u {
+ border-bottom: 1px solid #aaa;
+ text-decoration: none;
+}
+
+#field_container_see_also br {
+ margin-bottom: 10px;
+}
+
+.bz_alias_short_desc_container {
+ background: none;
+ font-size: 24px;
+ font-weight: normal;
+ line-height: 32px;
+ padding: 5px 0;
+ text-shadow: 0 1px rgba(255, 255, 255, 0.2);
+}
+
+.bz_alias_short_desc_container b {
+ font-weight: normal;
+}
+
+.bz_alias_short_desc_container .editme {
+ font-weight: normal;
+}
+
+.last_comment_link {
+ font-size: 12px;
+}
+
+.last_comment_link b {
+ border-bottom: 1px solid #aaa;
+ font-weight: normal;
+}
+
+table.edit_form {
+ background: #fff;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ margin-bottom: 20px;
+ padding: 10px 10px 80px;
+ position: relative;
+}
+
+table.edit_form tbody {
+ width: 100%;
+}
+
+table.edit_form hr {
+ display: none;
+}
+
+.field_label {
+ font-weight: normal !important;
+ padding-right: 20px;
+}
+
+.field_label a, .field_label b {
+ color: #000;
+ font-weight: normal;
+}
+
+.field_value .text_input {
+ min-width: 0;
+}
+
+#product, #component {
+ width: 235px;
+}
+
+#bz_show_bug_column_1 tr:last-child span {
+ position: absolute;
+ left: 20px;
+ bottom: 20px;
+}
+
+#commit_top {
+ position: absolute;
+ bottom: 20px;
+ right: 20px;
+}
+
+.cc_list_display {
+ background: #fff;
+ float: none;
+ font-size: 11px;
+ margin-top: 3px;
+ max-width: none;
+ padding: 5px;
+}
+
+#project-flags, #custom-flags {
+ border-collapse: collapse;
+}
+
+#project-flags label, #custom-flags label {
+ margin-right: 10px;
+}
+
+#cf_crash_signature {
+ width: 100%;
+}
+
+#bz_big_form_parts br {
+ display: none;
+}
+
+#attachment_table {
+ background: #fff;
+ border: none;
+ border-collapse: collapse;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ margin-bottom: 40px;
+}
+
+#attachment_table td {
+ border: none;
+}
+
+#attachment_table th, .bz_attach_footer, .bz_time_tracking_table th {
+ background: #eee;
+ color: #404040;
+}
+
+/* .bz_comment {
+ background: transparent;
+ border: none;
+ margin: 0 0 30px;
+ padding: 0;
+ width: 674px;
+} */
+
+.bz_comment_table {
+ width: 90%;
+}
+
+.bz_comment {
+ width: 70em;
+}
+
+.bz_comment pre {
+ font: 13px/1.2 "Droid Sans Mono", Menlo, Monaco, "Courier New", Courier, monospace;
+}
+
+.bz_first_comment_head, .bz_comment_head {
+ font-weight: normal;
+ line-height: 2;
+ padding-bottom: 5px;
+ background-color: transparent;
+}
+
+.bz_comment_user a {
+ -moz-transition: all 0.25s linear 0s;
+ -webkit-transition: all 0.25s linear 0s;
+ transition: all 0.25s linear 0s;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ transition: all 0.25s linear 0s;
+ background: #0095dd;
+ color: #fff;
+ font-weight: bold;
+ padding: 5px;
+}
+
+.bz_comment_user a:hover {
+ -moz-transition: all 0.25s linear 0s;
+ -webkit-transition: all 0.25s linear 0s;
+ transition: all 0.25s linear 0s;
+ background: #00539f;
+ border: none;
+ text-decoration: none;
+}
+
+.new_user {
+ margin-left: 10px;
+}
+
+.ih_history {
+ padding: 0 !important;
+}
+
+.ih_history .bz_comment_head {
+ padding-bottom: 10px;
+}
+
+.ih_history_item:not(.ih_hidden) ~ .ih_history_item:not(.ih_hidden) {
+ margin-top: 10px;
+}
+
+.ih_history .bz_comment_user a {
+ background: #888;
+}
+
+.ih_history .bz_comment_user a:hover {
+ background: #555;
+}
+
+.bz_comment_text {
+ background: #fff;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ margin: 10px 0 0;
+ overflow: auto;
+ padding: 10px;
+ position: relative;
+}
+
+.bz_comment_text:after, .bz_comment_text:before {
+ bottom: 100%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+
+.bz_comment_text:after {
+ border-bottom-color: #fff;
+ border-width: 8px;
+ left: 16px;
+}
+
+.bz_comment_text span.quote {
+ background: #eee !important;
+ color: #444 !important;
+ display: block !important;
+ margin-top: 5px !important;
+ margin-bottom: -10px !important;
+ overflow: auto;
+ padding: 5px !important;
+ white-space: pre-wrap;
+}
+
+.ih_inlinehistory {
+ background: #eee;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ padding: 10px;
+ position: relative;
+ top: -1px;
+ z-index: 1;
+}
+
+#add_comment {
+ border: 1px solid #ccc;
+ border-width: 1px 0;
+ margin-bottom: 20px;
+ padding: 10px 0;
+}
+
+#add_comment > table {
+ border-collapse: collapse;
+ width: 661px;
+}
+
+#comment {
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+ margin: 5px 0 20px;
+ width: 661px !important;
+}
+
+#footer {
+ background: #fff;
+ border: none;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0;
+ color: #bbb;
+ margin-left: -15px;
+ padding: 20px;
+}
+
+#footer #useful-links {
+ background: url(footer-mozilla.png) no-repeat;
+ min-height: 24px;
+}
+
+#footer > * {
+ margin-right: auto;
+ margin-left: auto;
+ padding: 0 0 0 200px !important;
+ width: 80%;
+}
+
+#commit, #commit_top {
+ -moz-transition: all 0.25s linear 0s;
+ -webkit-transition: all 0.25s linear 0s;
+ transition: all 0.25s linear 0s;
+ background-color: rgb(101, 147, 36);
+ background-image: -moz-linear-gradient(rgb(129, 188, 46), rgb(101, 147, 36));
+ background-repeat: repeat-x;
+ border-radius: 0.25em 0.25em 0.25em 0.25em;
+ border: 0px none;
+ box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.1), 0px -2px 0px 0px rgba(0, 0, 0, 0.2) inset;
+ color: rgb(255, 255, 255);
+ cursor: pointer;
+ display: inline-block;
+ font-size: 14px;
+ height: 48px;
+ line-height: 48px;
+ padding: 0px 24px;
+ text-align: center;
+ text-decoration: none;
+ text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.25);
+}
+
+#commit:hover, #commit_top:hover {
+ -moz-transition: all 0.25s linear 0s;
+ -webkit-transition: all 0.25s linear 0s;
+ transition: all 0.25s linear 0s;
+ box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.1), 0px -2px 0px 0px rgba(0, 0, 0, 0.2) inset, 0px 12px 24px 2px rgb(131, 200, 34) inset;
+ color: rgb(255, 255, 255);
+ text-decoration: none;
+}
+
+.related_actions {
+ line-height: 19px;
+ padding: 5px 10px;
+}
+
+/* Attachments */
+
+#viewFrame {
+ background: #444;
+ border: 2px solid #222;
+ margin-bottom: 10px;
+}
+
+#editFrame, #viewDiffFrame, #viewFrame {
+ margin-left: 0;
+}
+
+#flags label {
+ font-weight: normal;
+}
+
+.tabs td.spacer {
+ background: transparent;
+}
+
+/* Smaller than standard 990 (devices and browsers) */
+@media only screen and (max-width: 989px) {
+ #header .links {
+ float: none;
+ }
+}
+
+/* Tablet Portrait size to standard 990 */
+@media only screen and (min-width: 768px) and (max-width: 989px) {
+ body {
+ min-width: 768px;
+ }
+
+ #header .wrapper, #bugzilla-body {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 768px;
+ }
+
+ #footer > * {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 448px;
+ }
+}
+
+/* All Mobile Sizes */
+@media only screen and (max-width: 767px) {
+ table.edit_form, table.edit_form > tbody > tr > td {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ display: block;
+ width: 100% !important;
+ }
+
+ .bz_column_spacer {
+ width: auto;
+ height: 20px;
+ }
+}
+
+
+
+/* Mobile Landscape Size to Tablet Portrait */
+@media only screen and (min-width: 480px) and (max-width: 767px) {
+ body {
+ min-width: 480px;
+ }
+
+ #header .wrapper, #bugzilla-body, #attachment_table,
+ .bz_comment, #add_comment > table, #comment {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 480px !important;
+ }
+
+ #footer > * {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 480px;
+ }
+}
+
+/* Mobile Portrait Size to Mobile Landscape Size */
+@media only screen and (max-width: 479px) {
+ body {
+ min-width: 100%;
+ }
+
+ #header .wrapper, #bugzilla-body, #attachment_table,
+ .bz_comment, #add_comment > table, #comment {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100% !important;
+ }
+
+ #footer > * {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ }
+}
diff --git a/skins/contrib/Mozilla/grain.png b/skins/contrib/Mozilla/grain.png
new file mode 100644
index 000000000..2980ee90e
--- /dev/null
+++ b/skins/contrib/Mozilla/grain.png
Binary files differ
diff --git a/skins/contrib/Mozilla/index.css b/skins/contrib/Mozilla/index.css
new file mode 100644
index 000000000..1dfb34a07
--- /dev/null
+++ b/skins/contrib/Mozilla/index.css
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This Source Code Form is "Incompatible With Secondary Licenses", as
+ * defined by the Mozilla Public License, v. 2.0. */
+
+#enter_bug {
+ background: url(bugzilla-papericon.png) no-repeat;
+}
+#query {
+ background: url(bugzilla-magnifier.png) no-repeat;
+}
+#account {
+ background: url(bugzilla-person-alternate.png) no-repeat;
+ margin-right: 0;
+}
+#get_help {
+ background: url(bugzilla-questionmark2.png) no-repeat !important;
+}
diff --git a/skins/contrib/Mozilla/noise.png b/skins/contrib/Mozilla/noise.png
new file mode 100644
index 000000000..97407ffd2
--- /dev/null
+++ b/skins/contrib/Mozilla/noise.png
Binary files differ
diff --git a/skins/contrib/Mozilla/search.png b/skins/contrib/Mozilla/search.png
new file mode 100644
index 000000000..a56b5e2cd
--- /dev/null
+++ b/skins/contrib/Mozilla/search.png
Binary files differ
diff --git a/skins/custom/IE-fixes.css b/skins/custom/IE-fixes.css
new file mode 100644
index 000000000..0d5c47630
--- /dev/null
+++ b/skins/custom/IE-fixes.css
@@ -0,0 +1,4 @@
+.bz_short_desc_column a, .bz_short_short_desc_column a {
+ /* color:inherit */
+ color: expression(this.parentNode.currentStyle['color']);
+}
diff --git a/skins/custom/bug_groups.css b/skins/custom/bug_groups.css
new file mode 100644
index 000000000..3f999c11f
--- /dev/null
+++ b/skins/custom/bug_groups.css
@@ -0,0 +1,29 @@
+/* colorize bugs in various groups */
+body[class*=bz_group_] {
+ background-color: #e0e0ff;
+ border-left: solid red 2px;
+ padding-left: 13px;
+}
+
+body[class*=bz_group_] #bugzilla-body {
+ background-color: inherit;
+}
+
+body.bz_group_infrasec {
+ background-color: #ffcc99;
+}
+
+body.bz_group_webtools-security,
+body.bz_group_websites-security,
+body.bz_group_bugzilla-security {
+ background-color: #ffeeee;
+}
+
+body.bz_group_client-services-security,
+body.bz_group_mozilla-services-security {
+ background-color: #ffff80;
+}
+
+body.bz_group_core-security {
+ background-color: #ffe0b0;
+}
diff --git a/skins/custom/buglist.css b/skins/custom/buglist.css
new file mode 100644
index 000000000..d3097aedd
--- /dev/null
+++ b/skins/custom/buglist.css
@@ -0,0 +1,41 @@
+/* For the JS-sorting buglist. */
+
+th.sorttable_sorted,
+th.sorttable_sorted_reverse,
+th.sorted_0 {
+ background-color: #aaa;
+}
+
+th.sorted_1 {
+ background-color: #bbb;
+}
+
+th.sorted_2 {
+ background-color: #ccc;
+}
+
+th.sorted_3 {
+ background-color: #ddd;
+}
+
+th.sorted_4 {
+ background-color: #eee;
+}
+
+th.sorted_5 {
+ background-color: #fff;
+}
+
+.bz_short_desc_column a, .bz_short_short_desc_column a {
+ text-decoration: none;
+ color: inherit;
+}
+
+.bz_short_desc_column a:hover, .bz_short_short_desc_column a:hover {
+ text-decoration: underline;
+}
+
+#request_form #filtering th {
+ padding-left: 0.5em;
+}
+
diff --git a/skins/custom/create_bug.css b/skins/custom/create_bug.css
new file mode 100644
index 000000000..b1164aa75
--- /dev/null
+++ b/skins/custom/create_bug.css
@@ -0,0 +1,34 @@
+
+#bug_project_flags .field_label,
+#bug_tracking_flags .field_label {
+ font-weight: normal !important;
+}
+
+#guided {
+ margin-top: 30px;
+}
+
+#component {
+ width: 25em;
+}
+
+.hidden_text {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+
+#bug_create_warning {
+ border: 1px solid #dddddd;
+ background: #fff9db;
+ color: #666458;
+ padding: 5px;
+}
+
+#bug_create_warning_image {
+ float: left;
+ padding: 5px;
+}
+
+#bug_create_warning_text {
+ margin-left: 42px;
+}
diff --git a/skins/custom/global.css b/skins/custom/global.css
new file mode 100644
index 000000000..e80f656fb
--- /dev/null
+++ b/skins/custom/global.css
@@ -0,0 +1,67 @@
+/*
+ * Custom rules for skins/standard/global.css.
+ * The rules you put here override rules in that stylesheet.
+ */
+
+body {
+ margin: 0;
+ padding: 15px 15px 2px 15px;
+}
+
+#header .btn, #header .txt {
+ font-size: 100%;
+}
+
+#header #information {
+ color: #dddddd;
+ font-size: small;
+}
+
+pre {
+ font-size: medium;
+}
+
+#attachment_table {
+ width: 50em;
+}
+
+#page-index #quicksearchForm {
+ padding-top: 20px;
+}
+
+/* createaccount styling */
+.support_div {
+ width: 40%;
+ font-size: 80%;
+}
+
+.support_div > img {
+ padding: 5px 20px;
+}
+
+a {
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.controller {
+ font-size: 100%;
+ border: 1px solid #c0c0c0;
+ padding: 3px;
+}
+
+#footer .outro {
+ text-align:left;
+ padding-left:1ex;
+ padding-bottom:1ex;
+}
+
+.group_secure > th > a {
+ background-image: url("../../images/padlock.png");
+ background-position: center left;
+ background-repeat: no-repeat;
+ padding-left: 18px;
+}
diff --git a/skins/custom/index.css b/skins/custom/index.css
new file mode 100644
index 000000000..0c6884124
--- /dev/null
+++ b/skins/custom/index.css
@@ -0,0 +1,31 @@
+/*
+ * Custom rules for index.css.
+ * The rules you put here override rules in that stylesheet.
+ */
+
+/* index.html.tmpl puts intro hook contents inside a div which causes
+ * the icons to display over two rows when adding the Help icon.
+ * So we change to inline to make it display a single row. */
+#page-index .intro { display: inline; }
+
+#get_help { background: url(../standard/index/help.png) no-repeat; }
+
+.bz_common_actions {
+ display: block;
+ height: 170px;
+ width: 145px;
+ float: left;
+ margin: 0 2ex 2em 0;
+ text-align: center;
+}
+.bz_common_actions span {
+ position: relative;
+ top: 95%;
+ font-weight: bold;
+}
+.bz_common_actions,
+.bz_common_actions:visited,
+.bz_common_actions:hover
+{
+ text-decoration: none;
+}
diff --git a/skins/custom/search_form.css b/skins/custom/search_form.css
new file mode 100644
index 000000000..1855eb445
--- /dev/null
+++ b/skins/custom/search_form.css
@@ -0,0 +1,6 @@
+
+/* let the browser choose the select height from the "size" param */
+.search_field_grid select {
+ height: auto;
+}
+
diff --git a/skins/custom/show_bug.css b/skins/custom/show_bug.css
new file mode 100644
index 000000000..1a89a6892
--- /dev/null
+++ b/skins/custom/show_bug.css
@@ -0,0 +1,86 @@
+/*
+ * Custom rules for show_bug.css.
+ * The rules you put here override rules in that stylesheet.
+ */
+
+.last_comment_link {
+ float: right;
+ font-size: 80%;
+ font-weight: normal;
+ margin-left: 1em;
+}
+
+#legal_disclaimer {
+ width: 40em;
+ padding: 1em;
+ margin: 0 1em 1em 1em;
+ font-weight: bold;
+ border: 1px red solid;
+ background-color: lightyellow;
+}
+
+.bz_patch {
+ background: #ffffcc;
+}
+
+.cc_list_display {
+ list-style: none;
+ margin:0px;
+ padding:5px;
+ padding-right:20px;
+ overflow:auto;
+ float:left;
+ max-width:465px;
+ max-height:100px;
+ border:1px solid #CCC;
+}
+
+.cc_list_display li {
+ margin:0px;
+ padding:0px;
+ white-space:nowrap;
+}
+
+#wave_wand {
+ margin-top: 0px;
+}
+
+/* put the width on the TD rather than the PRE to stop the col resizing
+ when comments are hidden */
+.bz_comment {
+ width: 55em;
+}
+.bz_comment_text {
+ width: auto;
+}
+
+.bz_comment_number {
+ float: right;
+}
+
+/* style all field labels the same */
+
+.field_label, .field_label a {
+ color: #000;
+ font-weight: bold;
+}
+
+.field_label a {
+ cursor: help;
+}
+
+.edit_form table th:first-child {
+ width: 0px;
+}
+
+#bz_show_bug_column_1, #bz_show_bug_column_2 {
+ width: 50%;
+}
+
+/* fix flag table's vertical alignment */
+
+table#flags {
+ border-collapse: collapse;
+ border-spacing: 0px;
+}
+
diff --git a/skins/standard/buglist.css b/skins/standard/buglist.css
index ebebfb3ef..320635500 100644
--- a/skins/standard/buglist.css
+++ b/skins/standard/buglist.css
@@ -119,7 +119,7 @@ td.bz_total {
margin-top: .25em;
}
-.bz_query_explain {
+.bz_query_debug {
text-align: left;
}
@@ -127,3 +127,17 @@ td.bz_total {
color: inherit;
}
+/* The "filtering" table is specific to request.cgi.
+ * Same for the "requests" class used for tables. */
+
+#filtering #requester, #filtering #requestee {
+ min-width: 8em;
+}
+
+#filtering th {
+ text-align: right;
+}
+
+table.requests th {
+ text-align: left;
+}
diff --git a/skins/standard/enter_bug.css b/skins/standard/enter_bug.css
index 88d9e9e85..34be42f7a 100644
--- a/skins/standard/enter_bug.css
+++ b/skins/standard/enter_bug.css
@@ -69,4 +69,4 @@
/* Make the Add Me to CC button never wrap. */
#possible_duplicates .yui-dt-col-update_token { white-space: nowrap; }
-form#Create #possible_duplicates td { vertical-align: middle; } \ No newline at end of file
+form#Create #possible_duplicates td { vertical-align: middle; }
diff --git a/skins/standard/global.css b/skins/standard/global.css
index 4d4b02153..f50ccd02d 100644
--- a/skins/standard/global.css
+++ b/skins/standard/global.css
@@ -365,6 +365,10 @@ div#docslinks {
white-space: pre;
}
+.bz_comment_text span.quote_wrapped {
+ color: #65379c;
+}
+
table#flags th,
table#flags td {
vertical-align: middle;
@@ -380,7 +384,7 @@ input.requestee {
}
#error_msg {
- font-size: x-large;
+ font-size: large;
}
.warning {
@@ -388,9 +392,9 @@ input.requestee {
}
.throw_error {
- background-color: #ff0000;
+ background-color: #ff6666;
color: black;
- font-size: 120%;
+ font-size: large;
margin: 1em;
padding: 0.5em 1em;
}
diff --git a/skins/standard/guided.css b/skins/standard/guided.css
new file mode 100644
index 000000000..efecfe3ce
--- /dev/null
+++ b/skins/standard/guided.css
@@ -0,0 +1,4 @@
+#somebugs {
+ width: 100%;
+ height: 500px;
+}
diff --git a/skins/standard/reports.css b/skins/standard/reports.css
index 00272fdba..205946550 100644
--- a/skins/standard/reports.css
+++ b/skins/standard/reports.css
@@ -90,3 +90,8 @@
color: #333;
}
+.component_hilite {
+ background-color: lightgreen;
+ margin: 0;
+ padding: 1em 0;
+}
diff --git a/t/001compile.t b/t/001compile.t
index 97a339b2d..a2176babd 100644
--- a/t/001compile.t
+++ b/t/001compile.t
@@ -45,6 +45,11 @@ sub compile_file {
# Bugzilla::Install::CPAN.)
local @INC = @INC;
+ if ($file =~ /extensions/) {
+ skip "$file: extensions not tested", 1;
+ return;
+ }
+
if ($file =~ s/\.pm$//) {
$file =~ s{/}{::}g;
use_ok($file);
diff --git a/t/004template.t b/t/004template.t
index 3b858c0b3..ce18619e7 100644
--- a/t/004template.t
+++ b/t/004template.t
@@ -60,11 +60,16 @@ my $fh;
# fall back to English if necessary.
foreach my $file (@referenced_files) {
- my $path = File::Spec->catfile($english_default_include_path, $file);
- if (-e $path) {
- ok(1, "$path exists");
+ my @path = map(File::Spec->catfile($_, $file), @include_paths);
+ push(@path, File::Spec->catfile($english_default_include_path, $file));
+ my $found;
+ foreach my $path (@path) {
+ $found = $path if -e $path;
+ }
+ if ($found) {
+ ok(1, "$file exists");
} else {
- ok(0, "$path cannot be located --ERROR");
+ ok(0, "$file cannot be located --ERROR");
}
}
diff --git a/t/008filter.t b/t/008filter.t
index e73d23835..d0c0311f6 100644
--- a/t/008filter.t
+++ b/t/008filter.t
@@ -175,7 +175,8 @@ sub directive_ok {
return 1 if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE|
BLOCK|USE|ELSE|NEXT|LAST|DEFAULT|FLUSH|
ELSIF|SET|SWITCH|CASE|WHILE|RETURN|STOP|
- TRY|CATCH|FINAL|THROW|CLEAR|MACRO|FILTER)/x;
+ TRY|CATCH|FINAL|THROW|CLEAR|MACRO|FILTER|
+ CALL)/x;
# ? :
if ($directive =~ /.+\?(.+):(.+)/) {
@@ -224,7 +225,7 @@ sub directive_ok {
return 1 if $directive =~ /FILTER\ (html|csv|js|base64|css_class_quote|ics|
quoteUrls|time|uri|xml|lower|html_light|
obsolete|inactive|closed|unitconvert|
- txt|html_linebreak|none)\b/x;
+ txt|html_linebreak|none|json)\b/x;
return 0;
}
diff --git a/t/012throwables.t b/t/012throwables.t
index 3738ad524..590fb8aa5 100644
--- a/t/012throwables.t
+++ b/t/012throwables.t
@@ -62,7 +62,7 @@ foreach my $include_path (@include_paths) {
$file =~ s/\s.*$//; # nuke everything after the first space
$file =~ s|\\|/|g if ON_WINDOWS; # convert \ to / in path if on windows
$test_templates{$file} = ()
- if $file =~ m#global/(code|user)-error\.html\.tmpl#;
+ if $file =~ m#global/(code|user)-error(?:-errors)?\.html\.tmpl#;
}
}
@@ -75,7 +75,7 @@ plan tests => $tests;
# Collect all errors defined in templates
foreach my $file (keys %test_templates) {
- $file =~ m|template/([^/]+).*/global/([^/]+)-error\.html\.tmpl|;
+ $file =~ m|template/([^/]+).*/global/([^/]+)-error(?:-errors)?\.html\.tmpl|;
my $lang = $1;
my $errtype = $2;
diff --git a/t/Support/Files.pm b/t/Support/Files.pm
index 6c6e0ee57..2898fdd3f 100644
--- a/t/Support/Files.pm
+++ b/t/Support/Files.pm
@@ -23,14 +23,25 @@
package Support::Files;
+use Bugzilla;
+
use File::Find;
@additional_files = ();
@files = glob('*');
-find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, 'Bugzilla');
+my @extension_paths = map { $_->package_dir } @{ Bugzilla->extensions };
+find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, 'Bugzilla', @extension_paths);
push(@files, 'extensions/create.pl');
+my @extensions = glob('extensions/*');
+foreach my $extension (@extensions) {
+ # Skip disabled extensions
+ next if -e "$extension/disabled";
+
+ find(sub { push(@files, $File::Find::name) if $_ =~ /\.pm$/;}, $extension);
+}
+
sub isTestingFile {
my ($file) = @_;
my $exclude;
diff --git a/template/en/default/account/auth/login-small.html.tmpl b/template/en/default/account/auth/login-small.html.tmpl
index a9d86036a..216c4ed8a 100644
--- a/template/en/default/account/auth/login-small.html.tmpl
+++ b/template/en/default/account/auth/login-small.html.tmpl
@@ -47,6 +47,7 @@
id="mini_login[% qs_suffix FILTER html %]"
onsubmit="return check_mini_login_fields( '[% qs_suffix FILTER html %]' );"
>
+
<input id="Bugzilla_login[% qs_suffix FILTER html %]"
class="bz_login"
name="Bugzilla_login"
@@ -76,8 +77,8 @@
id="log_in[% qs_suffix %]">
<script type="text/javascript">
mini_login_constants = {
- "login" : "login",
- "warning" : "You must set the login and password before logging in."
+ "login" : "email address",
+ "warning" : "You must set the email address and password before logging in."
};
[%# We need this event to fire after autocomplete, because it does
# something different depending on whether or not there's already
@@ -109,7 +110,8 @@
});
}
</script>
- <a href="#" onclick="return hide_mini_login_form('[% qs_suffix %]')">[x]</a>
+ <a href="#" id="hide_mini_login[% qs_suffix FILTER html %]"
+ onclick="return hide_mini_login_form('[% qs_suffix %]')">[x]</a>
</form>
</li>
<li id="forgot_container[% qs_suffix %]">
diff --git a/template/en/default/account/auth/login.html.tmpl b/template/en/default/account/auth/login.html.tmpl
index 3de52b6a0..0aac403a5 100644
--- a/template/en/default/account/auth/login.html.tmpl
+++ b/template/en/default/account/auth/login.html.tmpl
@@ -37,14 +37,14 @@
[% USE Bugzilla %]
<p>
- I need a legitimate login and password to continue.
+ I need an email address and password to continue.
</p>
<form name="login" action="[% target FILTER html %]" method="POST"
[%- IF Bugzilla.cgi.param("data") %] enctype="multipart/form-data"[% END %]>
<table>
<tr>
- <th align="right"><label for="Bugzilla_login">Login:</label></th>
+ <th align="right"><label for="Bugzilla_login">Email Address:</label></th>
<td>
<input size="35" id="Bugzilla_login" name="Bugzilla_login">
[% Param('emailsuffix') FILTER html %]
@@ -64,7 +64,7 @@
<td>
<input type="checkbox" id="Bugzilla_remember" name="Bugzilla_remember" value="on"
[%+ "checked" IF Param('rememberlogin') == "defaulton" %]>
- <label for="Bugzilla_remember">Remember my Login</label>
+ <label for="Bugzilla_remember">Remember my email address</label>
</td>
</tr>
[% END %]
@@ -112,7 +112,7 @@
<form id="forgot" method="get" action="token.cgi">
<input type="hidden" name="a" value="reqpw">
If you have an account, but have forgotten your password,
- enter your login name below and submit a request
+ enter your email address below and submit a request
to change your password.<br>
<input size="35" name="loginname">
<input type="hidden" id="token" name="token" value="[% issue_hash_token(['reqpw']) FILTER html %]">
diff --git a/template/en/default/account/create.html.tmpl b/template/en/default/account/create.html.tmpl
index 5acd9f541..985a54841 100644
--- a/template/en/default/account/create.html.tmpl
+++ b/template/en/default/account/create.html.tmpl
@@ -77,4 +77,6 @@
<input type="submit" id="send" value="Send">
</form>
+[% Hook.process('additional_methods') %]
+
[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/account/prefs/email.html.tmpl b/template/en/default/account/prefs/email.html.tmpl
index 96a111bae..ffb153785 100644
--- a/template/en/default/account/prefs/email.html.tmpl
+++ b/template/en/default/account/prefs/email.html.tmpl
@@ -46,9 +46,12 @@
function SetCheckboxes(setting) {
for (var count = 0; count < document.userprefsform.elements.length; count++) {
var theinput = document.userprefsform.elements[count];
- if (theinput.type == "checkbox" && !theinput.disabled) {
+ if (theinput.type == "checkbox"
+ && !theinput.disabled
+ && !theinput.name.match("remove_ignored_bug"))
+ {
if (theinput.name.match("neg")) {
- theinput.checked = false;
+ theinput.checked = !setting;
}
else {
theinput.checked = setting;
@@ -119,6 +122,8 @@ document.write('<input type="button" value="Disable All Mail" onclick="SetCheckb
description = "A new $terms.bug is created" },
{ id = constants.EVT_OPENED_CLOSED,
description = "The $terms.bug is resolved or reopened" },
+ { id = constants.EVT_COMPONENT,
+ description = "The product or component changes" },
{ id = constants.EVT_PROJ_MANAGEMENT,
description = "The priority, status, severity, or milestone changes" },
{ id = constants.EVT_COMMENT,
@@ -284,6 +289,40 @@ You are currently not watching any users.
[% END %]
</p>
-<hr>
+<b>Ignore [% terms.Bugs %]</b>
-<br>
+<p>
+ You can specify a list of [% terms.bugs %] from which you never want to get
+ any email notification of any kind by adding their ID(s) as a comma-separated
+ list. Removing [% terms.abug %] by selecting it from the current ignored list
+ will re-enable email notifications for the [% terms.bug %].
+</p>
+[% IF user.bugs_ignored.size %]
+ <p>
+ You are currently ignoring:
+ <table>
+ [% FOREACH bug = user.bugs_ignored %]
+ <tr>
+ <td>
+ <input type="checkbox" name="remove_ignored_bug_[% bug.id FILTER html %]" value="1">
+ </td>
+ <td><a href="[% urlbase FILTER html %]show_bug.cgi?id=[% bug.id FILTER uri %]">
+ [% bug.id FILTER html %]</a>
+ </td>
+ <td>[% bug.status FILTER html %]</td>
+ <td>
+ [% IF user.can_see_bug(bug.id) %]
+ - [% bug.summary FILTER html %]
+ [% ELSE %]
+ (private)
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </p>
+[% END %]
+
+<p>Add [% terms.bugs %]:<br>
+ <input type="text" id="add_ignored_bugs"
+ name="add_ignored_bugs" size="60"></p>
diff --git a/template/en/default/account/prefs/permissions.html.tmpl b/template/en/default/account/prefs/permissions.html.tmpl
index 5e8dc9ca2..d3c787b07 100644
--- a/template/en/default/account/prefs/permissions.html.tmpl
+++ b/template/en/default/account/prefs/permissions.html.tmpl
@@ -65,9 +65,9 @@
There are no permission bits set on your account.
[% END %]
- [% IF user.in_group('editusers') %]
+ [% IF user.in_group('admin') %]
<br>
- You have editusers privileges. You can turn on and off
+ You have admin privileges. You can turn on and off
all permissions for all users.
[% ELSIF set_bits.size %]
<br>
diff --git a/template/en/default/account/prefs/saved-searches.html.tmpl b/template/en/default/account/prefs/saved-searches.html.tmpl
index 1b78592ca..ce9623372 100644
--- a/template/en/default/account/prefs/saved-searches.html.tmpl
+++ b/template/en/default/account/prefs/saved-searches.html.tmpl
@@ -67,6 +67,7 @@
Share With a Group
</th>
[% END %]
+ [% Hook.process('saved-header') %]
</tr>
<tr>
<td>My [% terms.Bugs %]</td>
@@ -145,6 +146,7 @@
[% END %]
</td>
[% END %]
+ [% Hook.process('saved-row') %]
</tr>
[% END %]
</table>
diff --git a/template/en/default/account/profile-activity.html.tmpl b/template/en/default/account/profile-activity.html.tmpl
index ee00875fe..aa6a63e85 100644
--- a/template/en/default/account/profile-activity.html.tmpl
+++ b/template/en/default/account/profile-activity.html.tmpl
@@ -35,7 +35,7 @@
#%]
[% title = BLOCK %]
- Account History for '[% otheruser.login FILTER html %]'
+ [% IF action == 'admin_activity' %]Admin[% ELSE %]Account[% END %] History for '[% otheruser.login FILTER html %]'
[% END %]
diff --git a/template/en/default/admin/flag-type/edit.html.tmpl b/template/en/default/admin/flag-type/edit.html.tmpl
index 2cb985a47..46346d2ea 100644
--- a/template/en/default/admin/flag-type/edit.html.tmpl
+++ b/template/en/default/admin/flag-type/edit.html.tmpl
@@ -231,6 +231,8 @@
</td>
</tr>
+ [% Hook.process('rows') %]
+
<tr>
<th>&nbsp;</th>
<td>
diff --git a/template/en/default/admin/params/advanced.html.tmpl b/template/en/default/admin/params/advanced.html.tmpl
index a8e8a297b..1cf0c344f 100644
--- a/template/en/default/admin/params/advanced.html.tmpl
+++ b/template/en/default/admin/params/advanced.html.tmpl
@@ -78,4 +78,12 @@
_ " use the <code>http://user:pass@proxy_url/</code> syntax.",
strict_transport_security => sts_desc,
+
+ disable_bug_updates =>
+ "When enabled, all updates to $terms.bugs will be blocked.",
+
+ arecibo_server =>
+ "When set, important errors and warnings will be sent to the"
+ _ " specified Arecibo server. Enter the Arecibo server's full URL;"
+ _ " eg <code>https://arecibo.example.com/v/1/</code>.",
} %]
diff --git a/template/en/default/admin/params/auth.html.tmpl b/template/en/default/admin/params/auth.html.tmpl
index 2e11dffbc..7a8d34791 100644
--- a/template/en/default/admin/params/auth.html.tmpl
+++ b/template/en/default/admin/params/auth.html.tmpl
@@ -107,6 +107,12 @@
"front page will require a login. No anonymous users will " _
"be permitted.",
+ webservice_email_filter => "Filter email addresses returned by the WebService API depending on " _
+ "if the user is logged in or not. This works similarly to how the " _
+ "web UI currently filters email addresses. If <tt>requirelogin</tt> " _
+ "is enabled, then this parameter has no effect as users must be logged " _
+ "in to use Bugzilla.",
+
emailregexp => "This defines the regexp to use for legal email addresses. The " _
"default tries to match fully qualified email addresses. Another " _
"popular value to put here is <tt>^[^@]+$</tt>, which means " _
diff --git a/template/en/default/admin/users/edit.html.tmpl b/template/en/default/admin/users/edit.html.tmpl
index 3efa4b8bf..010cacb73 100644
--- a/template/en/default/admin/users/edit.html.tmpl
+++ b/template/en/default/admin/users/edit.html.tmpl
@@ -116,9 +116,15 @@
<input type="hidden" name="token" value="[% token FILTER html %]">
[% INCLUDE listselectionhiddenfields %]
- or <a href="editusers.cgi?action=activity&amp;userid=[% otheruser.id %]"
- title="View Account History for '
- [%- otheruser.login FILTER html %]'">View Account History</a>
+ [% IF editusers %], [% ELSE %] or [% END %]
+ <a href="editusers.cgi?action=activity&amp;userid=[% otheruser.id %]"
+ title="View Account History for '
+ [%- otheruser.login FILTER html %]'">View Account History</a>
+ [% IF editusers %]
+ or <a href="editusers.cgi?action=admin_activity&amp;userid=[% otheruser.id %]"
+ title="View Account History for '
+ [%- otheruser.login FILTER html %]'">View Admin History</a>
+ [% END %]
</p>
</form>
<p>
diff --git a/template/en/default/admin/users/list.html.tmpl b/template/en/default/admin/users/list.html.tmpl
index 3f745a458..4d1d35c95 100644
--- a/template/en/default/admin/users/list.html.tmpl
+++ b/template/en/default/admin/users/list.html.tmpl
@@ -51,6 +51,17 @@
]
%]
+[% IF editusers %]
+ [% columns.push({
+ heading => 'Admin History'
+ content => 'View'
+ contentlink => 'editusers.cgi?action=admin_activity' _
+ '&amp;userid=%%userid%%' _
+ listselectionurlparams
+ })
+ %]
+[% END %]
+
[% IF Param('allowuserdeletion') && editusers %]
[% columns.push({heading => 'Action'
content => 'Delete'
diff --git a/template/en/default/attachment/createformcontents.html.tmpl b/template/en/default/attachment/createformcontents.html.tmpl
index 5b04382b6..7f738c07f 100644
--- a/template/en/default/attachment/createformcontents.html.tmpl
+++ b/template/en/default/attachment/createformcontents.html.tmpl
@@ -54,6 +54,7 @@
<th>Content Type:</th>
<td>
<em>If the attachment is a patch, check the box below.</em><br>
+ [% Hook.process("patch_notes") %]
<input type="checkbox" id="ispatch" name="ispatch" value="1"
onchange="setContentTypeDisabledState(this.form);">
<label for="ispatch">patch</label><br><br>
@@ -99,6 +100,7 @@
{type => "image/gif", desc => "GIF image"},
{type => "image/jpeg", desc => "JPEG image"},
{type => "image/png", desc => "PNG image"},
+ {type => "application/pdf", desc => "PDF document"},
{type => "application/octet-stream", desc => "binary file"}]
%]
[% Hook.process("mimetypes", "attachment/createformcontents.html.tmpl") %]
diff --git a/template/en/default/attachment/delete_reason.txt.tmpl b/template/en/default/attachment/delete_reason.txt.tmpl
index e4a1fc41f..87175c1a3 100644
--- a/template/en/default/attachment/delete_reason.txt.tmpl
+++ b/template/en/default/attachment/delete_reason.txt.tmpl
@@ -16,17 +16,10 @@
[%# INTERFACE:
# attachment: object of the attachment the user wants to delete.
# reason: string; The reason provided by the user.
- # date: the date when the request to delete the attachment was made.
#%]
-The content of attachment [% attachment.id %] has been deleted by
- [%+ user.identity %]
-[% IF reason %]
-who provided the following reason:
+The content of attachment [% attachment.id %] has been deleted
+[%~ IF reason %] for the following reason:
[%+ reason %]
-[% ELSE %]
-without providing any reason.
[% END %]
-
-The token used to delete this attachment was generated at [% date FILTER time %].
diff --git a/template/en/default/attachment/diff-footer.html.tmpl b/template/en/default/attachment/diff-footer.html.tmpl
index 49c662a98..e9965a9a8 100644
--- a/template/en/default/attachment/diff-footer.html.tmpl
+++ b/template/en/default/attachment/diff-footer.html.tmpl
@@ -20,6 +20,12 @@
</form>
+[% IF !file_count %]
+<div id="error_msg" class="throw_error">
+ No valid patch files were found in the attachment.
+</div>
+[% END %]
+
[% IF headers %]
<br>
diff --git a/template/en/default/attachment/diff-header.html.tmpl b/template/en/default/attachment/diff-header.html.tmpl
index c13b2e7ba..8cb5525f7 100644
--- a/template/en/default/attachment/diff-header.html.tmpl
+++ b/template/en/default/attachment/diff-header.html.tmpl
@@ -133,15 +133,18 @@ Interdiff of #[% oldid %] and #[% newid %] for [% terms.bug %] #[% bugid %]
[% END %]
[% IF warning %]
-<h2 class="warning">Warning:
+<h2 class="warning">
+ Warning:
[% IF warning == "interdiff1" %]
- this difference between two patches may show things in the wrong places due
- to a limitation in [% terms.Bugzilla %] when comparing patches with different
- sets of files.
- [% END %]
- [% IF warning == "interdiff2" %]
- this difference between two patches may be inaccurate due to a limitation in
- [%+ terms.Bugzilla %] when comparing patches made against different revisions.
+ this difference between two patches may show things in the wrong places due
+ to a limitation in [% terms.Bugzilla %] when comparing patches with
+ different sets of files.
+ [% ELSIF warning == "interdiff2" %]
+ this difference between two patches may be inaccurate due to a limitation
+ in [%+ terms.Bugzilla %] when comparing patches made against different
+ revisions.
+ [% ELSIF warning == "interdiff3" %]
+ interdiff encountered errors while comparing these patches.
[% END %]
</h2>
[% ELSE %]
diff --git a/template/en/default/attachment/edit.html.tmpl b/template/en/default/attachment/edit.html.tmpl
index 95ad4d335..530b2d04c 100644
--- a/template/en/default/attachment/edit.html.tmpl
+++ b/template/en/default/attachment/edit.html.tmpl
@@ -306,10 +306,17 @@
<div id="attachment_list">
Attachments on [% "$terms.bug ${attachment.bug_id}" FILTER bug_link(attachment.bug_id) FILTER none %]:
[% FOREACH a = attachments %]
- [% IF a == attachment.id %]
- [%+ a %]
+ [% IF a.isobsolete %]
+ <span class="bz_obsolete">
+ [% END %]
+ [% IF a.id == attachment.id %]
+ [%+ a.id FILTER html %]
[% ELSE %]
- <a href="attachment.cgi?id=[% a %]&amp;action=edit">[% a %]</a>
+ <a href="attachment.cgi?id=[% a.id FILTER uri %]&amp;action=edit"
+ title="[% a.description FILTER html %]">[% a.id FILTER html %]</a>
+ [% END %]
+ [% IF a.isobsolete %]
+ </span>
[% END %]
[% " |" UNLESS loop.last() %]
[% END %]
diff --git a/template/en/default/attachment/list.html.tmpl b/template/en/default/attachment/list.html.tmpl
index fa8e4774e..5079a0eec 100644
--- a/template/en/default/attachment/list.html.tmpl
+++ b/template/en/default/attachment/list.html.tmpl
@@ -64,6 +64,7 @@ function toggle_display(link) {
[% count = 0 %]
[% obsolete_attachments = 0 %]
+ [% user_cache = template_cache.users %]
[% FOREACH attachment = attachments %]
[% count = count + 1 %]
@@ -102,7 +103,14 @@ function toggle_display(link) {
title="Go to the comment associated with the attachment">
[%- attachment.attached FILTER time %]</a>,
- [% INCLUDE global/user.html.tmpl who = attachment.attacher %]
+ [%# No need to recreate the exact same template if we already have it. %]
+ [% attacher_id = attachment.attacher.id %]
+ [% UNLESS user_cache.$attacher_id %]
+ [% user_cache.$attacher_id = BLOCK %]
+ [% INCLUDE global/user.html.tmpl who = attachment.attacher %]
+ [% END %]
+ [% END %]
+ [% user_cache.$attacher_id FILTER none %]
</span>
</td>
diff --git a/template/en/default/bug/comments.html.tmpl b/template/en/default/bug/comments.html.tmpl
index e3099d94a..a876fb081 100644
--- a/template/en/default/bug/comments.html.tmpl
+++ b/template/en/default/bug/comments.html.tmpl
@@ -25,8 +25,65 @@
<script src="[% 'js/comments.js' FILTER mtime %]" type="text/javascript">
</script>
+<script type="text/javascript">
+<!--
+ /* Adds the reply text to the 'comment' textarea */
+ function replyToComment(id, real_id, name) {
+ var prefix = "(In reply to " + name + " from comment #" + id + ")\n";
+ var replytext = "";
+ [% IF user.settings.quote_replies.value == 'quoted_reply' %]
+ /* pre id="comment_name_N" */
+ var text_elem = document.getElementById('comment_text_'+id);
+ var text = getText(text_elem);
+ replytext = prefix + wrapReplyText(text);
+ [% ELSIF user.settings.quote_replies.value == 'simple_reply' %]
+ replytext = prefix;
+ [% END %]
+
+ [% IF user.is_insider %]
+ if (document.getElementById('isprivate_' + real_id).checked) {
+ document.getElementById('newcommentprivacy').checked = 'checked';
+ updateCommentTagControl(document.getElementById('newcommentprivacy'), 'comment');
+ }
+ [% END %]
+
+ /* Remove embedded links to attachment details */
+ replytext = replytext.replace(/(attachment\s+\d+)(\s+\[[^\[\n]+\])+/gi, '$1');
+
+ /* <textarea id="comment"> */
+ var textarea = document.getElementById('comment');
+ if (textarea.value != replytext) {
+ textarea.value += replytext;
+ }
+
+ textarea.focus();
+ }
+
+ function toggleCommentWrap(a, id) {
+ var spans = document.getElementById('comment_text_' + id).getElementsByTagName('span');
+ var old_class;
+ var new_class;
+ if (a.innerHTML == 'wrap') {
+ a.innerHTML = 'unwrap';
+ old_class = 'quote';
+ new_class = 'quote_wrapped';
+ } else {
+ a.innerHTML = 'wrap';
+ old_class = 'quote_wrapped';
+ new_class = 'quote';
+ }
+ for (var i = 0, l = spans.length; i < l; i++) {
+ if (spans[i].className == old_class)
+ spans[i].className = new_class;
+ }
+ return false;
+ }
+//-->
+</script>
+
[% DEFAULT start_at = 0 mode = "show" %]
[% sort_order = user.settings.comment_sort_order.value %]
+[% user_cache = template_cache.users %]
[%# NOTE: (start_at > 0) means we came here from a midair collision,
# in which case we don't care what the user's preference is.
@@ -35,23 +92,36 @@
[% sort_order = "oldest_to_newest" %]
[% END %]
+
+[%# Set up the variables as needed, depending on the sort order %]
+[% IF sort_order == "oldest_to_newest" %]
+ [% count = 0 %]
+ [% description = 0 %]
+ [% increment = 1 %]
+[% ELSE %]
+ [% increment = -1 %]
+ [% IF sort_order == "newest_to_oldest" %]
+ [% count = comments.size - 1 %]
+ [% description = 0 %]
+ [% ELSIF sort_order == "newest_to_oldest_desc_first" %]
+ [% count = comments.size %]
+ [% description = comments.size %]
+ [% END %]
+[% END %]
+
+[% Hook.process("comment_banner") %]
+
<!-- This auto-sizes the comments and positions the collapse/expand links
to the right. -->
<table class="bz_comment_table" cellpadding="0" cellspacing="0"><tr>
<td>
[% FOREACH comment = comments %]
- [% IF comment.count >= start_at %]
+ [% IF count >= start_at %]
[% PROCESS a_comment %]
[% END %]
-[% END %]
-
-[% IF user.settings.comment_box_position.value == "before_comments" && user.id %]
- <div class="bz_add_comment">
- <a href="#"
- onclick="return goto_add_comments();">
- Add Comment</a>
- </div>
+
+ [% count = count + increment %]
[% END %]
[%# Note: this template is used in multiple places; if you use this hook,
@@ -67,11 +137,6 @@
return false;">Collapse All Comments</a></li>
<li><a href="#" onclick="toggle_all_comments('expand');
return false;">Expand All Comments</a></li>
- [% IF user.settings.comment_box_position.value == "after_comments" && user.id %]
- <li class="bz_add_comment"><a href="#"
- onclick="return goto_add_comments('bug_status_bottom');">
- Add Comment</a></li>
- [% END %]
</ul>
[% END %]
</td>
@@ -82,40 +147,50 @@
[%############################################################################%]
[% BLOCK a_comment %]
- [% RETURN IF comment.is_private AND ! user.is_insider %]
+ [% RETURN IF comment.is_private AND NOT (user.is_insider || user.id == comment.author.id) %]
[% comment_text = comment.body_full %]
[% RETURN IF comment_text == '' AND (comment.work_time - 0) != 0 AND !user.is_timetracker %]
- <div id="c[% comment.count %]" class="bz_comment[% " bz_private" IF comment.is_private %]
- [% " bz_comment_hilite" IF marks.${comment.count} %]
- [% " bz_first_comment" IF comment.count == 0 %]">
- [% IF comment.count == 0 %]
+ <div id="c[% count %]" class="bz_comment[% " bz_private" IF comment.is_private %]
+ [% " bz_comment_hilite" IF marks.$count %]
+ [% " bz_first_comment" IF count == description %]">
+ [% IF count == description %]
[% class_name = "bz_first_comment_head" %]
[% comment_label = "Description" %]
[% ELSE %]
[% class_name = "bz_comment_head" %]
- [% comment_label = "Comment " _ comment.count %]
+ [% comment_label = "Comment " _ count %]
[% END %]
<div class="[% class_name FILTER html %]">
[% IF mode == "edit" %]
<span class="bz_comment_actions">
+ [% IF comment_text.search("(?:^>|\n>)") %]
+ [<a class="bz_wrap_link" href="#"
+ onclick="return toggleCommentWrap(this, [% count %])">wrap</a>]
+ [% END %]
+ [% IF bug.check_can_change_field('longdesc', 1, 0) %]
+ [<a class="bz_reply_link" href="#add_comment"
+ [% IF user.settings.quote_replies.value != 'off' %]
+ onclick="replyToComment('[% count %]', '[% comment.id %]', '[% comment.author.name || comment.author.nick FILTER html FILTER js %]'); return false;"
+ [% END %]
+ >reply</a>]
+ [% END %]
<script type="text/javascript"><!--
- addReplyLink([% comment.count %], [% comment.id %]);
- addCollapseLink([% comment.count %], 'Toggle comment display'); // -->
+ addCollapseLink([% count %], 'Toggle comment display'); // -->
</script>
</span>
[% END %]
- [% IF mode == "edit" && user.is_insider %]
+ [% IF mode == "edit" && user.is_insider && bug.check_can_change_field('longdesc', 0, 1) %]
<div class="bz_private_checkbox">
<input type="hidden" value="1"
name="defined_isprivate_[% comment.id %]">
<input type="checkbox"
name="isprivate_[% comment.id %]" value="1"
id="isprivate_[% comment.id %]"
- onClick="updateCommentPrivacy(this, [% comment.count %])"
+ onClick="updateCommentPrivacy(this, [% count %])"
[% " checked=\"checked\"" IF comment.is_private %]>
<label for="isprivate_[% comment.id %]">Private</label>
</div>
@@ -123,17 +198,24 @@
<span class="bz_comment_number">
<a
- href="show_bug.cgi?id=[% bug.bug_id %]#c[% comment.count %]">
+ href="show_bug.cgi?id=[% bug.bug_id %]#c[% count %]">
[%- comment_label FILTER html %]</a>
</span>
<span class="bz_comment_user">
- [% INCLUDE global/user.html.tmpl who = comment.author %]
- </span>
+ [%# No need to recreate the exact same template if we already have it. %]
+ [% commenter_id = comment.author.id %]
+ [% UNLESS user_cache.$commenter_id %]
+ [% user_cache.$commenter_id = BLOCK %]
+ [% INCLUDE global/user.html.tmpl who = comment.author %]
+ [% END %]
+ [% END %]
+ [% user_cache.$commenter_id FILTER none %]
+ [% Hook.process('user', 'bug/comments.html.tmpl') %]
+ </span>
<span class="bz_comment_user_images">
- [% FOREACH group = comment.author.direct_group_membership %]
- [% NEXT UNLESS group.icon_url %]
+ [% FOREACH group = comment.author.groups_with_icon %]
<img src="[% group.icon_url FILTER html %]"
alt="[% group.name FILTER html %]"
title="[% group.name FILTER html %] - [% group.description FILTER html %]">
@@ -156,8 +238,9 @@
# generated HTML
#%]
<pre class="bz_comment_text"
- [% ' id="comment_text_' _ comment.count _ '"' IF mode == "edit" %]>
+ [% ' id="comment_text_' _ count _ '"' IF mode == "edit" %]>
[%- comment_text FILTER quoteUrls(bug, comment) -%]
</pre>
</div>
+ [% Hook.process('a_comment-end', 'bug/comments.html.tmpl') %]
[% END %]
diff --git a/template/en/default/bug/create/comment-guided.txt.tmpl b/template/en/default/bug/create/comment-guided.txt.tmpl
index df04d8fb5..67748e594 100644
--- a/template/en/default/bug/create/comment-guided.txt.tmpl
+++ b/template/en/default/bug/create/comment-guided.txt.tmpl
@@ -41,7 +41,7 @@ Steps to Reproduce:
[%+ cgi.param("reproduce_steps") %]
[% END %]
-[% IF cgi.param("actual_results") -%]
+[% IF cgi.param("actual_results") %]
Actual Results:
[%+ cgi.param("actual_results") %]
[% END %]
diff --git a/template/en/default/bug/create/create-guided.html.tmpl b/template/en/default/bug/create/create-guided.html.tmpl
index d10314628..43437bcd7 100644
--- a/template/en/default/bug/create/create-guided.html.tmpl
+++ b/template/en/default/bug/create/create-guided.html.tmpl
@@ -31,22 +31,12 @@
[% PROCESS global/header.html.tmpl
title = "Enter $terms.ABug"
onload = "PutDescription()"
- style = "#somebugs { width: 100%; height: 500px }"
+ style_urls = [ "skins/standard/guided.css" ]
%]
[% style = "" %]
-<p>
- <font color="red">
- This is a template used on mozilla.org. This template, and the
- comment-guided.txt.tmpl template that formats the data submitted via
- the form in this template, are included as a demo of what it's
- possible to do with custom templates in general, and custom [% terms.bug %]
- entry templates in particular. As much of the text will not apply,
- you should alter it
- if you want to use this form on your [% terms.Bugzilla %] installation.
- </font>
-</p>
+[% INCLUDE 'bug/create/user-message.html.tmpl' %]
[% tablecolour = "#FFFFCC" %]
@@ -80,15 +70,15 @@ function PutDescription() {
[%# Include other products if sensible %]
[% IF product.name == "Firefox" %]
- [% productstring = "product=Mozilla%20Application%20Suite&amp;product=Firefox" %]
+ [% productstring = "product=Toolkit&amp;product=Core&amp;product=Firefox" %]
[% ELSIF product.name == "Thunderbird" %]
- [% productstring = "product=Mozilla%20Application%20Suite&amp;product=Thunderbird" %]
+ [% productstring = "product=MailNews%20Core&amp;product=Thunderbird" %]
[% ELSE %]
[% productstring = BLOCK %]product=[% product.name FILTER uri %][% END %]
[% END %]
<p>
- <a href="duplicates.cgi?[% productstring %]&amp;format=simple" target="somebugs">All-time Top 100</a> (loaded initially) |
+ <a href="duplicates.cgi?[% productstring %]&amp;format=simple" target="somebugs">All-time Top 20</a> (loaded initially) |
<a href="duplicates.cgi?[% productstring %]&amp;format=simple&amp;sortby=delta&amp;reverse=1&amp;maxrows=100&amp;changedsince=14" target="somebugs">Hot in the last two weeks</a>
</p>
@@ -112,14 +102,14 @@ function PutDescription() {
<input type="hidden" name="product" value="[% product.name FILTER html %]">
[% IF product.name == "Firefox" OR
product.name == "Thunderbird" OR
- product.name == "Mozilla Application Suite" OR
+ product.name == "SeaMonkey" OR
product.name == "Camino" %]
<input type="hidden" name="product" value="Core">
<input type="hidden" name="product" value="Toolkit">
- <input type="hidden" name="product" value="PSM">
<input type="hidden" name="product" value="NSPR">
<input type="hidden" name="product" value="NSS">
- [% END %]
+ <input type="hidden" name="product" value="MailNews Core">
+ [% END %]
<input type="hidden" name="chfieldfrom" value="-6m">
<input type="hidden" name="chfieldto" value="Now">
<input type="hidden" name="chfield" value="[Bug creation]">
@@ -215,7 +205,7 @@ function PutDescription() {
[%# We override rep_platform and op_sys for simplicity. The values chosen
are based on which are most common in the b.m.o database %]
- [% rep_platform = [ "PC", "Macintosh", "All", "Other" ] %]
+ [% rep_platform = [ "x86", "x86_64", "PowerPC", "All", "Other" ] %]
<tr bgcolor="[% tablecolour %]">
<td align="right" valign="top">
@@ -238,7 +228,7 @@ function PutDescription() {
</td>
</tr>
- [% IF product.name.match("Firefox|Camino|Mozilla Application Suite") %]
+ [% IF product.name.match("Firefox|Camino|SeaMonkey") %]
[% matches = cgi.user_agent('Gecko/(\d+)') %]
[% buildid = cgi.user_agent() IF matches %]
[% END %]
@@ -257,8 +247,8 @@ function PutDescription() {
<p>
This should identify the exact version of the product you were using.
If the above field is blank or you know it is incorrect, copy the
- version text from the product's Help |
- About menu (for browsers this will begin with "Mozilla/5.0...").
+ user agent text from the product's Help | Troubleshooting Information menu
+ (for browsers this will begin with "Mozilla/5.0...").
If the product won't start, instead paste the complete URL you downloaded
it from.
</p>
@@ -275,7 +265,7 @@ function PutDescription() {
URL that demonstrates the problem you are seeing (optional).<br>
<b>IMPORTANT</b>: if the problem is with a broken web page, you need
to report it
- <a href="https://bugzilla.mozilla.org/page.cgi?id=broken-website.html">a different way</a>.
+ <a href="http://input.mozilla.com/feedback">a different way</a>.
</p>
</td>
</tr>
@@ -418,10 +408,7 @@ function PutDescription() {
%]
<p>
Add any additional information you feel may be
- relevant to this [% terms.bug %], such as the <b>theme</b> you were
- using (does the [% terms.bug %] still occur
- with the default theme?), a
- <b><a href="http://kb.mozillazine.org/Quality_Feedback_Agent">Talkback crash ID</a></b>, or special
+ relevant to this [% terms.bug %], such as special
information about <b>your computer's configuration</b>. Any information
longer than a few lines, such as a <b>stack trace</b> or <b>HTML
testcase</b>, should be added
@@ -431,13 +418,12 @@ function PutDescription() {
into your URL bar.
<br>
<br>
- If you are reporting a crash, note the module in
- which the software crashed (e.g., <tt>Application Violation in
- gkhtml.dll</tt>).
+ If you are reporting a crash, please <a href="https://developer.mozilla.org/En/How_to_get_a_stacktrace_for_a_bug_report
+">try and get a stack trace</a>, which tells us exactly where things went wrong.
</p>
</td>
</tr>
-
+
<tr>
<td valign="top" align="right">
<b>Severity</b>
diff --git a/template/en/default/bug/create/create.html.tmpl b/template/en/default/bug/create/create.html.tmpl
index 634bcf326..7f2087467 100644
--- a/template/en/default/bug/create/create.html.tmpl
+++ b/template/en/default/bug/create/create.html.tmpl
@@ -32,16 +32,37 @@
title = title
yui = [ 'autocomplete', 'calendar', 'datatable', 'button' ]
style_urls = [ 'skins/standard/attachment.css',
- 'skins/standard/enter_bug.css' ]
+ 'skins/standard/enter_bug.css',
+ 'skins/custom/create_bug.css' ]
javascript_urls = [ "js/attachment.js", "js/util.js",
- "js/field.js", "js/TUI.js", "js/bug.js" ]
- onload = "set_assign_to(); hideElementById('attachment_true');
- showElementById('attachment_false'); showElementById('btn_no_attachment');"
+ "js/field.js", "js/TUI.js", "js/bug.js",
+ "js/create_bug.js" ]
+ onload = "init();"
%]
<script type="text/javascript">
<!--
+function init() {
+ set_assign_to();
+ hideElementById('attachment_true');
+ showElementById('attachment_false');
+ showElementById('btn_no_attachment');
+ initCrashSignatureField();
+ init_take_handler('[% user.login FILTER js %]');
+}
+
+function initCrashSignatureField() {
+ var el = document.getElementById('cf_crash_signature');
+ if (!el) return;
+ [% IF cf_crash_signature.length %]
+ YAHOO.util.Dom.addClass('cf_crash_signature_container', 'bz_default_hidden');
+ [% ELSE %]
+ hideEditableField('cf_crash_signature_container','cf_crash_signature_input',
+ 'cf_crash_signature_action', 'cf_crash_signature');
+ [% END %]
+}
+
var initialowners = new Array([% product.components.size %]);
var last_initialowner;
var initialccs = new Array([% product.components.size %]);
@@ -60,11 +81,9 @@ var flags = new Array([% product.components.size %]);
initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]";
[% flag_list = [] %]
[% FOREACH f = c.flag_types.bug %]
- [% NEXT UNLESS f.is_active %]
[% flag_list.push(f.id) %]
[% END %]
[% FOREACH f = c.flag_types.attachment %]
- [% NEXT UNLESS f.is_active %]
[% flag_list.push(f.id) %]
[% END %]
flags[[% count %]] = [[% flag_list.join(",") FILTER js %]];
@@ -112,6 +131,14 @@ function set_assign_to() {
document.getElementById('initial_cc').innerHTML = initialccs[index];
document.getElementById('comp_desc').innerHTML = comp_desc[index];
+ if (initialccs[index]) {
+ showElementById('initial_cc_label');
+ showElementById('initial_cc');
+ } else {
+ hideElementById('initial_cc_label');
+ hideElementById('initial_cc');
+ }
+
[% IF Param("useqacontact") %]
var contact = initialqacontacts[index];
if (qa_contact == last_initialqacontact
@@ -122,30 +149,31 @@ function set_assign_to() {
}
[% END %]
- // First, we disable all flags. Then we re-enable those
- // which are available for the selected component.
- var inputElements = document.getElementsByTagName("select");
- var inputElement, flagField;
- for ( var i=0 ; i<inputElements.length ; i++ ) {
- inputElement = inputElements.item(i);
- if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) {
- var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1");
- inputElement.disabled = true;
- // Also hide the requestee field, if it exists.
- inputElement = document.getElementById("requestee_type-" + id);
- if (inputElement)
- YAHOO.util.Dom.addClass(inputElement.parentNode, 'bz_default_hidden');
+ // We show or hide the available flags depending on the selected component.
+ var flag_rows = YAHOO.util.Dom.getElementsByClassName('bz_flag_type', 'tbody');
+ for (var i = 0; i < flag_rows.length; i++) {
+ // Each flag table row should have one flag form select element
+ // We get the flag type id from the id attribute of the select.
+ var flag_select = YAHOO.util.Dom.getElementsByClassName('flag_select',
+ 'select',
+ flag_rows[i])[0];
+ var type_id = flag_select.id.split('-')[1];
+ var can_set = flag_select.options.length > 1 ? 1 : 0;
+ var show = 0;
+ // Loop through the allowed flag ids for the selected component
+ // and if we match, then show the row, otherwise hide the row.
+ for (var j = 0; j < flags[index].length; j++) {
+ if (flags[index][j] == type_id) {
+ show = 1;
+ break;
+ }
}
- }
- // Now enable flags available for the selected component.
- for (var i = 0; i < flags[index].length; i++) {
- flagField = document.getElementById("flag_type-" + flags[index][i]);
- // Do not enable flags the user cannot set nor request.
- if (flagField && flagField.options.length > 1) {
- flagField.disabled = false;
- // Re-enabling the requestee field depends on the status
- // of the flag.
- toggleRequesteeField(flagField, 1);
+ if (show && can_set) {
+ flag_select.disabled = false;
+ YAHOO.util.Dom.removeClass(flag_rows[i], 'bz_default_hidden');
+ } else {
+ flag_select.disabled = true;
+ YAHOO.util.Dom.addClass(flag_rows[i], 'bz_default_hidden');
}
}
}
@@ -185,9 +213,8 @@ TUI_hide_default('attachment_text_field');
<tr>
<td colspan="2">
- <a id="expert_fields_controller" class="controller bz_default_hidden"
- href="javascript:TUI_toggle_class('expert_fields')">Hide
- Advanced Fields</a>
+ <input type="button" id="expert_fields_controller"
+ value="Hide Advanced Fields" onClick="toggleAdvancedFields()">
[%# Show the link if the browser supports JS %]
<script type="text/javascript">
YAHOO.util.Dom.removeClass('expert_fields_controller',
@@ -349,121 +376,78 @@ TUI_hide_default('attachment_text_field');
bug = default, field = bug_fields.bug_status,
editable = (bug_status.size > 1), value = default.bug_status
override_legal_values = bug_status %]
-
- <td>&nbsp;</td>
- [%# Calculate the number of rows we can use for flags %]
- [% num_rows = 6 + (Param("useqacontact") ? 1 : 0) +
- (user.is_timetracker ? 3 : 0) +
- (Param("usebugaliases") ? 1 : 0)
- %]
-
- <td rowspan="[% num_rows FILTER html %]">
- [% IF product.flag_types.bug.size > 0 %]
- [% display_flag_headers = 0 %]
- [% any_flags_requesteeble = 0 %]
-
- [% FOREACH flag_type = product.flag_types.bug %]
- [% NEXT UNLESS flag_type.is_active %]
- [% display_flag_headers = 1 %]
- [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %]
- [% END %]
-
- [% IF display_flag_headers %]
- [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types.bug
- any_flags_requesteeble = any_flags_requesteeble
- flag_table_id = "bug_flags"
- %]
- [% END %]
- [% END %]
- </td>
</tr>
<tr>
[% INCLUDE "bug/field-label.html.tmpl"
field = bug_fields.assigned_to editable = 1
%]
- <td colspan="2">
+ <td>
[% INCLUDE global/userselect.html.tmpl
- id => "assigned_to"
- name => "assigned_to"
- value => assigned_to
+ id => "assigned_to"
+ name => "assigned_to"
+ value => assigned_to
disabled => assigned_to_disabled
- size => 30
- emptyok => 1
+ size => 30
+ emptyok => 1
custom_userlist => assignees_list
- %]
+ %]
+ [% UNLESS assigned_to_disabled %]
+ <span id="take_bug">
+ &nbsp;(<a title="Assign to yourself" href="#"
+ onclick="return take_bug('[% user.login FILTER js %]')">take</a>)
+ </span>
+ [% END %]
<noscript>(Leave blank to assign to component's default assignee)</noscript>
</td>
- </tr>
[% IF Param("useqacontact") %]
- <tr>
- [% INCLUDE "bug/field-label.html.tmpl"
- field = bug_fields.qa_contact editable = 1
- %]
- <td colspan="2">
- [% INCLUDE global/userselect.html.tmpl
- id => "qa_contact"
- name => "qa_contact"
- value => qa_contact
- disabled => qa_contact_disabled
- size => 30
- emptyok => 1
- custom_userlist => qa_contacts_list
- %]
- <noscript>(Leave blank to assign to default qa contact)</noscript>
- </td>
- </tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.qa_contact editable = 1
+ %]
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "qa_contact"
+ name => "qa_contact"
+ value => qa_contact
+ disabled => qa_contact_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => qa_contacts_list
+ %]
+ <noscript>(Leave blank to assign to default qa contact)</noscript>
+ </td>
+ </tr>
[% END %]
<tr>
[% INCLUDE "bug/field-label.html.tmpl"
field = bug_fields.cc editable = 1
%]
- <td colspan="2">
+ <td>
[% INCLUDE global/userselect.html.tmpl
- id => "cc"
- name => "cc"
- value => cc
+ id => "cc"
+ name => "cc"
+ value => cc
disabled => cc_disabled
- size => 30
+ size => 30
multiple => 5
%]
+ </td>
+ <th>
+ <span id="initial_cc_label" class="bz_default_hidden">
+ Default [% field_descs.cc FILTER html %]:
+ </span>
+ </th>
+ <td>
+ <span id="initial_cc"></span>
</td>
</tr>
<tr>
- <th>Default [% field_descs.cc FILTER html %]:</th>
- <td colspan="2">
- <div id="initial_cc">
- </div>
- </td>
- </tr>
-
- <tr>
<td colspan="3">&nbsp;</td>
</tr>
-[% IF user.is_timetracker %]
- <tr>
- [% INCLUDE "bug/field-label.html.tmpl"
- field = bug_fields.estimated_time editable = 1
- %]
- <td colspan="2">
- <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]">
- </td>
- </tr>
- <tr>
- [% INCLUDE bug/field.html.tmpl
- bug = default, field = bug_fields.deadline, value = deadline,
- editable = 1, value_span = 2 %]
- </tr>
-
- <tr>
- <td colspan="3">&nbsp;</td>
- </tr>
-[% END %]
-
[% IF Param("usebugaliases") %]
<tr>
[% INCLUDE "bug/field-label.html.tmpl"
@@ -474,34 +458,9 @@ TUI_hide_default('attachment_text_field');
</td>
</tr>
[% END %]
-
- <tr>
- [% INCLUDE "bug/field-label.html.tmpl"
- field = bug_fields.bug_file_loc editable = 1
- %]
- <td colspan="2" class="field_value">
- <input name="bug_file_loc" id="bug_file_loc" class="text_input"
- size="40" value="[% bug_file_loc FILTER html %]">
- </td>
- </tr>
-</tbody>
-
-<tbody>
- [% USE Bugzilla %]
-
- [% FOREACH field = Bugzilla.active_custom_fields %]
- [% NEXT UNLESS field.enter_bug %]
- [% SET value = ${field.name}.defined ? ${field.name} : "" %]
- <tr [% 'class="expert_fields"' IF !field.is_mandatory %]>
- [% INCLUDE bug/field.html.tmpl
- bug = default, field = field, value = value, editable = 1,
- value_span = 3 %]
- </tr>
- [% END %]
</tbody>
<tbody>
-
<tr>
[% INCLUDE "bug/field-label.html.tmpl"
field = bug_fields.short_desc editable = 1
@@ -574,21 +533,17 @@ TUI_hide_default('attachment_text_field');
</td>
</tr>
- [% IF user.is_insider %]
- <tr class="expert_fields">
- <th>&nbsp;</th>
- <td colspan="3">
- &nbsp;&nbsp;
- <input type="checkbox" id="comment_is_private" name="comment_is_private"
- [% ' checked="checked"' IF comment_is_private %]
- onClick="updateCommentTagControl(this, 'comment')">
- <label for="comment_is_private">
- Make description and any new attachment private (visible only to members
- of the <strong>[% Param('insidergroup') FILTER html %]</strong> group)
- </label>
- </td>
- </tr>
- [% END %]
+<tbody class="expert_fields">
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.bug_file_loc editable = 1
+ %]
+ <td colspan="3" class="field_value">
+ <input name="bug_file_loc" id="bug_file_loc" class="text_input"
+ size="40" value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+</tbody>
[% IF Param("maxattachmentsize") || Param("maxlocalattachment") %]
<tr>
@@ -609,6 +564,16 @@ TUI_hide_default('attachment_text_field');
any_flags_requesteeble = 1
flag_table_id ="attachment_flags" %]
</table>
+
+ [% IF user.is_insider %]
+ <input type="checkbox" id="comment_is_private" name="comment_is_private"
+ [% ' checked="checked"' IF comment_is_private %]
+ onClick="updateCommentTagControl(this, 'comment')">
+ <label for="comment_is_private">
+ Make this attachment and [% terms.bug %] description private (visible only
+ to members of the <strong>[% Param('insidergroup') FILTER html %]</strong> group)
+ </label>
+ [% END %]
</fieldset>
</div>
</td>
@@ -618,41 +583,193 @@ TUI_hide_default('attachment_text_field');
<tbody class="expert_fields">
[% IF user.in_group('editbugs', product.id) %]
+ <tr>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.dependson editable = 1
+ %]
+ <td>
+ <input name="dependson" accesskey="d" value="[% dependson FILTER html %]" size="30">
+ </td>
+ [% INCLUDE "bug/field-label.html.tmpl"
+ field = bug_fields.blocked editable = 1
+ %]
+ <td>
+ <input name="blocked" accesskey="b" value="[% blocked FILTER html %]" size="30">
+ </td>
+ </tr>
+
[% IF use_keywords %]
<tr>
[% INCLUDE bug/field.html.tmpl
bug = default, field = bug_fields.keywords, editable = 1,
value = keywords, desc_url = "describekeywords.cgi",
- value_span = 2
+ value_span = 3
%]
</tr>
[% END %]
<tr>
- [% INCLUDE "bug/field-label.html.tmpl"
- field = bug_fields.dependson editable = 1
- %]
- <td colspan="3">
- <input name="dependson" accesskey="d" value="[% dependson FILTER html %]">
+ <th>Status Whiteboard:</th>
+ <td colspan="3" class="field_value">
+ <input id="status_whiteboard" name="status_whiteboard" size="70"
+ value="[% status_whiteboard FILTER html %]" class="text_input">
</td>
</tr>
+ [% END %]
+
+ [% IF user.is_timetracker %]
<tr>
[% INCLUDE "bug/field-label.html.tmpl"
- field = bug_fields.blocked editable = 1
+ field = bug_fields.estimated_time editable = 1
%]
- <td colspan="3">
- <input name="blocked" accesskey="b" value="[% blocked FILTER html %]">
+ <td>
+ <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]">
</td>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.deadline, value = deadline, editable = 1
+ %]
</tr>
[% END %]
</tbody>
+<tbody>
+[%# non-tracking flags custom fields %]
+[% FOREACH field = Bugzilla.active_custom_fields(product=>product,type=>1) %]
+ [% NEXT UNLESS field.enter_bug %]
+ [%# crash-signature gets custom handling %]
+ [% IF field.name == 'cf_crash_signature' %]
+ [% show_crash_signature = 1 %]
+ [% NEXT %]
+ [% END %]
+ [% SET value = ${field.name}.defined ? ${field.name} : "" %]
+ <tr [% 'class="expert_fields"' IF !field.is_mandatory %]>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = field, value = value, editable = 1,
+ value_span = 3 %]
+ </tr>
+[% END %]
+</tbody>
+
+[%# crash-signature handling %]
+[% IF show_crash_signature %]
+<tbody class="expert_fields">
+ <tr>
+ <th id="field_label_cf_crash_signature" class="field_label">
+ <label for="cf_crash_signature"> Crash Signature: </label>
+ </th>
+ <td colspan="3">
+ <span id="cf_crash_signature_container">
+ <span id="cf_crash_signature_nonedit_display"><i>None</i></span>
+ (<a id="cf_crash_signature_action" href="#">edit</a>)
+ </span>
+ <span id="cf_crash_signature_input">
+ <textarea id="cf_crash_signature" name="cf_crash_signature" rows="4" cols="60"
+ >[% cf_crash_signature FILTER html %]</textarea>
+ </span>
+ </td>
+ </tr>
+</tbody>
+[% END %]
+
+[% tracking_flags = [] %]
+[% project_flags = [] %]
+[% FOREACH field = Bugzilla.active_custom_fields(product=>product,type=>2) %]
+ [% NEXT UNLESS field.enter_bug %]
+ [% IF cf_is_project_flag(field.name) %]
+ [% project_flags.push(field) %]
+ [% ELSE %]
+ [% tracking_flags.push(field) %]
+ [% END %]
+[% END %]
+
+[% display_flags = 0 %]
+[% any_flags_requesteeble = 0 %]
+[% FOREACH flag_type = product.flag_types.bug %]
+ [% display_flags = 1 %]
+ [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %]
+ [% LAST IF display_flags && any_flags_requesteeable %]
+[% END %]
+
+[% IF project_flags.size || tracking_flags.size || display_flags %]
+ <tbody class="expert_fields">
+ <tr>
+ <th>Flags:</th>
+ <td colspan="3">
+ <div id="bug_flags_false" class="bz_default_hidden">
+ <input type="button" value="Set [% terms.bug FILTER html %] flags" onClick="handleWantsBugFlags(true)">
+ </div>
+
+ <div id="bug_flags_true">
+ <input type="button" id="btn_no_bug_flags" value="Don't set [% terms.bug %] flags"
+ class="bz_default_hidden" onClick="handleWantsBugFlags(false)">
+
+ <fieldset>
+ <legend>Set [% terms.bug %] flags</legend>
+
+ <table cellpadding="0" cellspacing="0">
+ <tr>
+ [% IF tracking_flags.size %]
+ <td [% IF project_flags.size %]rowspan="2"[% END %]>
+ <table id="bug_tracking_flags">
+ <tr>
+ <th colspan="2" style="text-align:left">Tracking Flags:</th>
+ </tr>
+ <tr>
+ [% FOREACH field = tracking_flags %]
+ [% SET value = ${field.name}.defined ? ${field.name} : "" %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = field, value = value, editable = 1,
+ value_span = 3 %]
+ </tr>
+ [% END %]
+ </tr>
+ </table>
+ </td>
+ [% END %]
+ [% IF project_flags.size %]
+ <td>
+ <table id="bug_project_flags">
+ <tr>
+ <th colspan="2" style="text-align:left">Project Flags:</th>
+ </tr>
+ <tr>
+ [% FOREACH field = project_flags %]
+ [% SET value = ${field.name}.defined ? ${field.name} : "" %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = field, value = value, editable = 1,
+ value_span = 3 %]
+ </tr>
+ [% END %]
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ [% END %]
+ [% IF display_flags %]
+ <td>
+ [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types.bug
+ any_flags_requesteeble = any_flags_requesteeble
+ flag_table_id = "bug_flags"
+ %]
+ </td>
+ [% END %]
+ </tr>
+ </table>
+ </fieldset>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+[% END %]
+
<tbody class="expert_fields">
[% IF product.groups_available.size %]
<tr>
<th>&nbsp;</th>
<td colspan="3">
- <br>
<strong>
Only users in all of the selected groups can view this
[%+ terms.bug %]:
@@ -662,7 +779,6 @@ TUI_hide_default('attachment_text_field');
(Leave all boxes unchecked to make this a public [% terms.bug %].)
</font>
<br>
- <br>
<!-- Checkboxes -->
<input type="hidden" name="defined_groups" value="1">
@@ -694,6 +810,13 @@ TUI_hide_default('attachment_text_field');
</td>
</tr>
</tbody>
+ [%# "status whiteboard" and "qa contact" are the longest labels
+ # add them here to avoid shifting the page when toggling advanced fields %]
+ <tr>
+ <th class="hidden_text">Status Whiteboard:</th>
+ <td>&nbsp;</td>
+ <th class="hidden_text">QA Contact:</th>
+ </tr>
</table>
<input type="hidden" name="form_name" value="enter_bug">
</form>
@@ -701,6 +824,13 @@ TUI_hide_default('attachment_text_field');
[%# Links or content with more information about the bug being created. %]
[% Hook.process("end") %]
+<div id="guided">
+ <a id="guided_img" href="enter_bug.cgi?format=guided&amp;product=[% product.name FILTER uri %]"><img
+ src="extensions/BMO/web/images/guided.png" width="16" height="16" border="0" align="absmiddle"></a>
+ <a id="guided_link" href="enter_bug.cgi?format=guided&amp;product=[% product.name FILTER uri %]"
+ >Switch to the [% terms.Bugzilla %] Helper</a>
+</div>
+
[% PROCESS global/footer.html.tmpl %]
[%############################################################################%]
diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl
index fbc6e4a96..c43935c2f 100644
--- a/template/en/default/bug/edit.html.tmpl
+++ b/template/en/default/bug/edit.html.tmpl
@@ -32,71 +32,6 @@
<script type="text/javascript">
<!--
- /* Outputs a link to call replyToComment(); used to reduce HTML output */
- function addReplyLink(id, real_id) {
- /* XXX this should really be updated to use the DOM Core's
- * createElement, but finding a container isn't trivial.
- */
- [% IF user.settings.quote_replies.value != 'off' %]
- document.write('[<a href="#add_comment" onclick="replyToComment(' +
- id + ',' + real_id + '); return false;">reply<' + '/a>]');
- [% END %]
- }
-
- /* Adds the reply text to the `comment' textarea */
- function replyToComment(id, real_id) {
- var prefix = "(In reply to comment #" + id + ")\n";
- var replytext = "";
- [% IF user.settings.quote_replies.value == 'quoted_reply' %]
- /* pre id="comment_name_N" */
- var text_elem = document.getElementById('comment_text_'+id);
- var text = getText(text_elem);
- replytext = prefix + wrapReplyText(text);
- [% ELSIF user.settings.quote_replies.value == 'simple_reply' %]
- replytext = prefix;
- [% END %]
-
- [% IF user.is_insider %]
- if (document.getElementById('isprivate_' + real_id).checked) {
- document.getElementById('newcommentprivacy').checked = 'checked';
- updateCommentTagControl(document.getElementById('newcommentprivacy'), 'comment');
- }
- [% END %]
-
- /* <textarea id="comment"> */
- var textarea = document.getElementById('comment');
- textarea.value += replytext;
-
- textarea.focus();
- }
-
- if (typeof Node == 'undefined') {
- /* MSIE doesn't define Node, so provide a compatibility object */
- window.Node = {
- TEXT_NODE: 3,
- ENTITY_REFERENCE_NODE: 5
- };
- }
-
- /* Concatenates all text from element's childNodes. This is used
- * instead of innerHTML because we want the actual text (and
- * innerText is non-standard).
- */
- function getText(element) {
- var child, text = "";
- for (var i=0; i < element.childNodes.length; i++) {
- child = element.childNodes[i];
- var type = child.nodeType;
- if (type == Node.TEXT_NODE || type == Node.ENTITY_REFERENCE_NODE) {
- text += child.nodeValue;
- } else {
- /* recurse into nodes of other types */
- text += getText(child);
- }
- }
- return text;
- }
-
[% IF user.is_timetracker %]
var fRemainingTime = [% bug.remaining_time %]; // holds the original value
function adjustRemainingTime() {
@@ -115,7 +50,6 @@
// if the remaining time is changed manually, update fRemainingTime
fRemainingTime = document.changeform.remaining_time.value;
}
-
[% END %]
[% IF user.id %]
@@ -164,34 +98,48 @@
[% PROCESS section_url_keyword_whiteboard %]
[% PROCESS section_spacer %]
-
- [%# *** Dependencies *** %]
+
+ [%# *** Dependencies and duplicates *** %]
+ [% PROCESS section_duplicates %]
+
[% PROCESS section_dependson_blocks %]
-
+
+ [% IF user.id %]
+ <tr>
+ <td colspan="2">
+ <span style="float:left">
+ <a href="page.cgi?id=fields.html">What do these fields mean?</a>
+ </span>
+ [% PROCESS commit_button id="_top"%]
+ </td>
+ </tr>
+ [% END %]
</table>
</td>
<td>
<div class="bz_column_spacer">&nbsp;</div>
</td>
[%# 2nd Column %]
- <td id="bz_show_bug_column_2" class="bz_show_bug_column">
+ <td id="bz_show_bug_column_2" class="bz_show_bug_column_table" valign="top">
<table cellpadding="3" cellspacing="1">
[%# *** Reported and modified dates *** %]
[% PROCESS section_dates %]
-
+
[% PROCESS section_cclist %]
-
+
+ [% PROCESS section_bug_ignored %]
+
[% PROCESS section_spacer %]
- [% PROCESS section_see_also %]
-
- [% PROCESS section_customfields %]
-
+ [% PROCESS section_flags %]
+
+ [% PROCESS section_see_also %]
+
[% PROCESS section_spacer %]
-
+
+ [% PROCESS section_customfields %]
+
[% Hook.process("after_custom_fields") %]
-
- [% PROCESS section_flags %]
</table>
</td>
@@ -220,6 +168,8 @@
[% IF user.settings.comment_box_position.value == 'before_comments' %]
[% PROCESS comment_box %]
+ [% ELSE %]
+ [% PROCESS summon_comment_box %]
[% END %]
</td>
<td>
@@ -238,7 +188,10 @@
[% IF user.settings.comment_box_position.value == 'after_comments' %]
<hr>
[% PROCESS comment_box %]
- [% END %]
+ [% ELSE %]
+ [% PROCESS summon_comment_box %]
+ [% END %]
+
</form>
@@ -249,7 +202,10 @@
[% BLOCK section_title %]
[%# That's the main table, which contains all editable fields. %]
<div class="bz_alias_short_desc_container edit_form">
- [% PROCESS commit_button id="_top"%]
+ <span class="last_comment_link">
+ <a href="#c[% bug.comments.size - 1 %]"
+ accesskey="l"><b>L</b>ast Comment</a>
+ </span>
<a href="show_bug.cgi?id=[% bug.bug_id %]">
[%-# %]<b>[% terms.Bug %]&nbsp;[% bug.bug_id FILTER html %]</b>
[%-# %]</a> -<span id="summary_alias_container" class="bz_default_hidden">
@@ -351,9 +307,9 @@
%]
</tr>
<tr>
- <td class="field_label">
- <label for="version"><b>Version</b></label>:
- </td>
+ <th class="field_label">
+ <label for="version">Version</label>:
+ </th>
[% PROCESS select selname => "version" %]
</tr>
@@ -361,9 +317,9 @@
[%# PLATFORM #%]
[%############%]
<tr>
- <td class="field_label">
- <label for="rep_platform" accesskey="h"><b>Platform</b></label>:
- </td>
+ <th class="field_label">
+ <label for="rep_platform" accesskey="h">Platform</label>:
+ </th>
<td class="field_value">
[% INCLUDE bug/field.html.tmpl
bug = bug, field = bug_fields.rep_platform,
@@ -373,9 +329,6 @@
bug = bug, field = bug_fields.op_sys,
no_tds = 1, value = bug.op_sys
editable = bug.check_can_change_field('op_sys', 0, 1) %]
- <script type="text/javascript">
- assignToDefaultOnChange(['product', 'component']);
- </script>
</td>
</tr>
@@ -389,9 +342,9 @@
[% BLOCK section_status %]
<tr>
- <td class="field_label">
- <b><a href="page.cgi?id=fields.html#status">Status</a></b>:
- </td>
+ <th class="field_label">
+ <a href="page.cgi?id=fields.html#status">Status</a>:
+ </th>
<td id="bz_field_status">
<span id="static_bug_status">
[% display_value("bug_status", bug.bug_status) FILTER html %]
@@ -408,6 +361,30 @@
</span>
</td>
</tr>
+ [% IF Param('usestatuswhiteboard') %]
+ <tr>
+ <th class="field_label">
+ <label for="status_whiteboard" accesskey="w"><u>W</u>hiteboard</label>:
+ </th>
+ [% PROCESS input inputname => "status_whiteboard" size => "40" colspan => 2 %]
+ </tr>
+ [% END %]
+
+ [% IF use_keywords %]
+ <tr>
+ <th class="field_label">
+ <label for="keywords" accesskey="k">
+ <a href="describekeywords.cgi"><u>K</u>eywords</a></label>:
+ </th>
+ <td class="field_value" colspan="2">
+ [% INCLUDE bug/field.html.tmpl
+ bug = bug, field = bug_fields.keywords, value = bug.keywords
+ editable = bug.check_can_change_field("keywords", 0, 1),
+ no_tds = 1
+ %]
+ </td>
+ </tr>
+ [% END %]
[% END %]
[%############################################################################%]
@@ -420,10 +397,10 @@
[%# Importance (priority and severity) #%]
[%###############################################################%]
<tr>
- <td class="field_label">
+ <th class="field_label">
<label for="priority" accesskey="i">
- <b><a href="page.cgi?id=fields.html#importance"><u>I</u>mportance</a></b></label>:
- </td>
+ <a href="page.cgi?id=fields.html#importance"><u>I</u>mportance</a></label>:
+ </th>
<td>
[% INCLUDE bug/field.html.tmpl
bug = bug, field = bug_fields.priority,
@@ -439,11 +416,11 @@
[% IF Param("usetargetmilestone") && bug.target_milestone %]
<tr>
- <td class="field_label">
+ <th class="field_label">
<label for="target_milestone">
- <a href="page.cgi?id=fields.html#target_milestone">
+ <a href="page.cgi?id=fields.html#target_milestone">
Target&nbsp;Milestone</a></label>:
- </td>
+ </th>
[% PROCESS select selname = "target_milestone" %]
</tr>
[% END %]
@@ -457,9 +434,9 @@
[% BLOCK section_people %]
<tr>
- <td class="field_label">
- <b><a href="page.cgi?id=fields.html#assigned_to">Assigned To</a></b>:
- </td>
+ <th class="field_label">
+ <a href="page.cgi?id=fields.html#assigned_to">Assigned To</a>:
+ </th>
<td>
[% IF bug.check_can_change_field("assigned_to", 0, 1) %]
<div id="bz_assignee_edit_container" class="bz_default_hidden">
@@ -506,41 +483,46 @@
[% IF Param('useqacontact') %]
<tr>
- <td class="field_label">
- <label for="qa_contact" accesskey="q"><b><u>Q</u>A Contact</b></label>:
- </td>
+ <th class="field_label">
+ <label for="qa_contact" accesskey="q"><u>Q</u>A Contact</label>:
+ </th>
<td>
[% IF bug.check_can_change_field("qa_contact", 0, 1) %]
- [% IF bug.qa_contact != "" %]
- <div id="bz_qa_contact_edit_container" class="bz_default_hidden">
+ <div id="bz_qa_contact_edit_container" class="bz_default_hidden">
<span>
- <span id="bz_qa_contact_edit_display">
- [% INCLUDE global/user.html.tmpl who = bug.qa_contact %]</span>
+ [% INCLUDE global/user.html.tmpl who = bug.qa_contact %]
(<a href="#" id="bz_qa_contact_edit_action">edit</a>)
+ [% IF bug.qa_contact.id != user.id %]
+ (<a title="Change QA contact to yourself"
+ href="#" id="bz_qa_contact_take_action">take</a>)
+ [% END %]
</span>
</div>
- [% END %]
<div id="bz_qa_contact_input">
[% INCLUDE global/userselect.html.tmpl
- id => "qa_contact"
- name => "qa_contact"
- value => bug.qa_contact.login
- size => 30
- classes => ["bz_userfield"]
- emptyok => 1
+ id => "qa_contact"
+ name => "qa_contact"
+ value => bug.qa_contact.login
+ size => 30
+ classes => ["bz_userfield"]
+ emptyok => 1
%]
<br>
<input type="checkbox" id="set_default_qa_contact" name="set_default_qa_contact" value="1">
<label for="set_default_qa_contact" id="set_default_qa_contact_label">Reset QA Contact to default</label>
</div>
<script type="text/javascript">
- [% IF bug.qa_contact != "" %]
- hideEditableField('bz_qa_contact_edit_container',
- 'bz_qa_contact_input',
- 'bz_qa_contact_edit_action',
- 'qa_contact',
- '[% bug.qa_contact.login FILTER js %]');
- [% END %]
+ hideEditableField('bz_qa_contact_edit_container',
+ 'bz_qa_contact_input',
+ 'bz_qa_contact_edit_action',
+ 'qa_contact',
+ '[% bug.qa_contact.login FILTER js %]');
+ hideEditableField('bz_qa_contact_edit_container',
+ 'bz_qa_contact_input',
+ 'bz_qa_contact_take_action',
+ 'qa_contact',
+ '[% bug.qa_contact.login FILTER js %]',
+ '[% user.login FILTER js %]');
initDefaultCheckbox('qa_contact');
</script>
[% ELSE %]
@@ -549,6 +531,11 @@
</td>
</tr>
[% END %]
+ <script type="text/javascript">
+ assignToDefaultOnChange(['product', 'component'],
+ '[% bug.component_obj.default_assignee.login FILTER js %]',
+ '[% bug.component_obj.default_qa_contact.login FILTER js %]');
+ </script>
[% END %]
[%############################################################################%]
@@ -564,14 +551,17 @@
<td>
[% IF bug.check_can_change_field("bug_file_loc", 0, 1) %]
<span id="bz_url_edit_container" class="bz_default_hidden">
- [% IF is_safe_url(bug.bug_file_loc) %]
- <a href="[% bug.bug_file_loc FILTER html %]" target="_blank"
- title="[% bug.bug_file_loc FILTER html %]">
- [% bug.bug_file_loc FILTER truncate(40) FILTER html %]</a>
- [% ELSE %]
- [% bug.bug_file_loc FILTER html %]
- [% END %]
- (<a href="#" id="bz_url_edit_action">edit</a>)</span>
+ <a href="[% bug.bug_file_loc FILTER html %]" target="_blank"
+ title="[% bug.bug_file_loc FILTER html %]"
+ [% IF NOT is_safe_url(bug.bug_file_loc) %]
+ onclick="return confirm(
+ 'This is considered an unsafe URL and could possibly be harmful. '
+ + 'The full URL is:\n\n[% bug.bug_file_loc FILTER js FILTER html %]\n\n'
+ + 'Continue?')"
+ [% END %]>
+ [% bug.bug_file_loc FILTER truncate(40) FILTER html %]</a>
+ (<a href="#" id="bz_url_edit_action">edit</a>)
+ </span>
[% END %]
<span id="bz_url_input_area">
[% url_output = PROCESS input no_td=1 inputname => "bug_file_loc" size => "40" colspan => 2 %]
@@ -593,36 +583,34 @@
[% END %]
</td>
</tr>
-
- [% IF Param('usestatuswhiteboard') %]
- <tr>
- <td class="field_label">
- <label for="status_whiteboard" accesskey="w"><b><u>W</u>hiteboard</b></label>:
- </td>
- [% PROCESS input inputname => "status_whiteboard" size => "40" colspan => 2 %]
- </tr>
- [% END %]
-
- [% IF use_keywords %]
- <tr>
- <td class="field_label">
- <label for="keywords" accesskey="k">
- <b><a href="describekeywords.cgi"><u>K</u>eywords</a></b></label>:
- </td>
- <td class="field_value" colspan="2">
- [% INCLUDE bug/field.html.tmpl
- bug = bug, field = bug_fields.keywords, value = bug.keywords
- editable = bug.check_can_change_field("keywords", 0, 1),
- no_tds = 1
- %]
- </td>
- </tr>
- [% END %]
[% END %]
[%############################################################################%]
-[%# Block for Depends On / Blocks #%]
+[%# Block for Duplicates #%]
+[%############################################################################%]
+
+[% BLOCK section_duplicates %]
+ [% RETURN UNLESS bug.duplicates.size %]
+ <tr>
+ <th class="field_label">
+ <label for="duplicates">Duplicates</label>:
+ </th>
+ <td class="field_value" colspan="2">
+ <span id="duplicates">
+ [% FOREACH dupe = bug.duplicates %]
+ [% dupe.id FILTER bug_link(dupe, use_alias => 1) FILTER none %][% " " %]
+ [% END %]
+ </span>
+ (<a href="buglist.cgi?bug_id=[% bug.duplicate_ids.join(",") FILTER html %]">
+ [%-%]view as [% terms.bug %] list</a>)
+ </td>
+ </tr>
+[% END %]
+
+[%############################################################################%]
+[%# Block for Depends On / Blocks #%]
[%############################################################################%]
+
[% BLOCK section_dependson_blocks %]
<tr>
[% INCLUDE dependencies
@@ -749,18 +737,18 @@
[% BLOCK section_dates %]
<tr>
- <td class="field_label">
- <b>Reported</b>:
- </td>
+ <th class="field_label">
+ Reported:
+ </th>
<td>
[% bug.creation_ts FILTER time %] by [% INCLUDE global/user.html.tmpl who = bug.reporter %]
</td>
</tr>
<tr>
- <td class="field_label">
- <b> Modified</b>:
- </td>
+ <th class="field_label">
+ Modified:
+ </th>
<td>
[% bug.delta_ts FILTER time FILTER replace(':\d\d$', '') FILTER replace(':\d\d ', ' ')%]
(<a href="show_activity.cgi?id=[% bug.bug_id %]">[%# terms.Bug %]History</a>)
@@ -774,9 +762,9 @@
[%############################################################################%]
[% BLOCK section_cclist %]
<tr>
- <td class="field_label">
- <label for="newcc" accesskey="a"><b>CC List</b>:</label>
- </td>
+ <th class="field_label">
+ <label for="newcc" accesskey="a">CC List:</label>
+ </th>
<td>
[% IF user.id %]
[% IF NOT bug.cc || NOT bug.cc.contains(user.login) %]
@@ -808,10 +796,17 @@
[% IF user.id || bug.cc.size %]
<span id="cc_edit_area_showhide_container" class="bz_default_hidden">
(<a href="#" id="cc_edit_area_showhide">[% IF user.id %]edit[% ELSE %]show[% END %]</a>)
- </span>
+ [% IF user.id && bug.cc.size %]
+ <br>
+ <ul class="cc_list_display">
+ [% FOREACH c = bug.cc %]
+ <li>[% c FILTER email FILTER html %]</li>
+ [% END %]
+ </ul>
+ [% END %]
+ </span>
[% END %]
<div id="cc_edit_area">
- <br>
[% IF user.id %]
<div>
<div><label for="cc"><b>Add</b></label></div>
@@ -864,6 +859,27 @@
[% END %]
[%############################################################################%]
+[%# Block for Bug Ignored #%]
+[%############################################################################%]
+[% BLOCK section_bug_ignored %]
+ [% IF user.id %]
+ <tr>
+ <th class="field_label">
+ <label for="bug_ignored" title="Ignore all email for this [% terms.bug %]">
+ Ignore [% terms.Bug %] Mail:
+ </label>
+ </th>
+ <td>
+ <input type="hidden" name="defined_bug_ignored" value="1">
+ <input type="checkbox" name="bug_ignored" id="bug_ignored" value="1"
+ [% ' checked="checked"' IF user.is_bug_ignored(bug.id) %]>
+ (never email me about this [% terms.bug %])
+ </td>
+ </tr>
+ [% END %]
+[% END %]
+
+[%############################################################################%]
[%# Block for See Also #%]
[%############################################################################%]
[% BLOCK section_see_also %]
@@ -885,26 +901,52 @@
[% BLOCK section_flags %]
[%# *** Flags *** %]
[% show_bug_flags = 0 %]
+ [% bug_flags_set = 0 %]
+ [% show_more_flags = 0 %]
[% FOREACH type = bug.flag_types %]
[% IF (type.flags && type.flags.size > 0) || (user.id && type.is_active) %]
[% show_bug_flags = 1 %]
- [% LAST %]
[% END %]
+ [% IF user.id && type.is_active && (type.flags.size == 0 || type.is_multiplicable) %]
+ [% show_more_flags = 1 %]
+ [% END %]
+ [% IF type.flags && type.flags.size > 0 %]
+ [% bug_flags_set = 1 %]
+ [% END %]
+ [% LAST IF show_bug_flags && show_more_flags && bug_flags_set %]
[% END %]
[% IF show_bug_flags %]
<tr>
- <td class="field_label flags_label">
- <label><b>Flags:</b></label>
- </td>
- <td></td>
- </tr>
- <tr>
- <td colspan="2">
+ <th class="field_label">
+ <label>Flags:</label>
+ </th>
+ <td>
[% IF bug.flag_types.size > 0 %]
[% PROCESS "flag/list.html.tmpl" flag_no_header = 1
flag_types = bug.flag_types
any_flags_requesteeble = bug.any_flags_requesteeble %]
[% END %]
+ [% IF show_more_flags && bug.check_can_change_field('flagtypes.name', 0, 1) %]
+ <span id="bz_flags_more_container" class="bz_default_hidden">
+ [% IF !bug_flags_set %]<em>None yet set</em>[% END %]
+ (<a href="#" id="bz_flags_more_action">[% IF !bug_flags_set %]set[% ELSE %]more[% END %] flags</a>)
+ </span>
+ <script type="text/javascript">
+ YAHOO.util.Dom.removeClass('bz_flags_more_container', 'bz_default_hidden');
+ var table = YAHOO.util.Dom.get("flags");
+ var rows = YAHOO.util.Dom.getElementsByClassName('bz_flag_type', 'tbody', table);
+ for (var i = 0; i < rows.length; i++) {
+ YAHOO.util.Dom.addClass(rows[i], 'bz_default_hidden');
+ }
+ YAHOO.util.Event.addListener('bz_flags_more_action', 'click', function (e) {
+ YAHOO.util.Dom.addClass('bz_flags_more_container', 'bz_default_hidden');
+ for (var i = 0; i < rows.length; i++) {
+ YAHOO.util.Dom.removeClass(rows[i], 'bz_default_hidden');
+ }
+ YAHOO.util.Event.preventDefault(e);
+ });
+ </script>
+ [% END %]
</td>
</tr>
[% END %]
@@ -917,7 +959,10 @@
[% BLOCK section_customfields %]
[%# *** Custom Fields *** %]
[% USE Bugzilla %]
- [% FOREACH field = Bugzilla.active_custom_fields %]
+ [% FOREACH field = Bugzilla.active_custom_fields(product=>bug.product_obj,component=>bug.component_obj,type=>1) %]
+ [% NEXT IF NOT user.id AND field.value == "---" %]
+ [% Hook.process('custom_field', 'bug/edit.html.tmpl') %]
+ [% NEXT IF field.hidden %]
<tr>
[% PROCESS bug/field.html.tmpl value = bug.${field.name}
editable = bug.check_can_change_field(field.name, 0, 1)
@@ -1068,7 +1113,7 @@
<label for="comment" accesskey="c"><b>Additional
<u>C</u>omments</b></label>:
- [% IF user.is_insider %]
+ [% IF user.is_insider && bug.check_can_change_field('longdesc', 0, 1) %]
<input type="checkbox" name="comment_is_private" value="1"
id="newcommentprivacy"
onClick="updateCommentTagControl(this, 'comment')">
@@ -1080,23 +1125,34 @@
<!-- This table keeps the submit button aligned with the box. -->
<table><tr><td>
- [% INCLUDE global/textarea.html.tmpl
- name = 'comment'
- id = 'comment'
- minrows = 10
- maxrows = 25
- cols = constants.COMMENT_COLS
- %]
- [% Hook.process("after_comment_textarea", 'bug/edit.html.tmpl') %]
+ [% IF bug.check_can_change_field('longdesc', 0, 1) %]
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ %]
+ [% Hook.process("after_comment_textarea", 'bug/edit.html.tmpl') %]
+ [% ELSE %]
+ <div id="comment">
+ <fieldset>
+ <legend>Note</legend>
+ You are not allowed to make an additional comment on this [% terms.bug %].
+ </fieldset>
+ </div>
+ [% END %]
<br>
[% PROCESS commit_button id=""%]
+ [% Hook.process("after_comment_commit_button", 'bug/edit.html.tmpl') %]
+
<table id="bug_status_bottom"
class="status" cellspacing="0" cellpadding="0">
<tr>
- <td class="field_label">
- <b><a href="page.cgi?id=fields.html#status">Status</a></b>:
- </td>
+ <th class="field_label">
+ <a href="page.cgi?id=fields.html#status">Status</a>:
+ </th>
<td>
[% PROCESS bug/knob.html.tmpl %]
</td>
@@ -1123,6 +1179,21 @@
</div>
[% END %]
+[% BLOCK summon_comment_box %]
+<div id="comment_top_hat">
+ <script type="text/javascript">
+ function summonCommentBox() {
+ var commentbox = document.getElementById('add_comment');
+ document.getElementById('comment_top_hat').appendChild(commentbox);
+ document.getElementById('wave_wand').style.display = 'none';
+ }
+ </script>
+ <p id="wave_wand">
+ <a href="javascript:summonCommentBox()"><i>Summon comment box</i></a>
+ </p>
+</div>
+[% END %]
+
[%############################################################################%]
[%# Block for SELECT fields #%]
[%############################################################################%]
@@ -1131,6 +1202,7 @@
<td>
[% IF bug.check_can_change_field(selname, 0, 1)
AND bug.choices.${selname}.size > 1 %]
+ <input type="hidden" id="[% selname %]_dirty">
<select id="[% selname %]" name="[% selname %]">
[% FOREACH x = bug.choices.${selname} %]
[% NEXT IF NOT x.is_active AND x.name != bug.${selname} %]
diff --git a/template/en/default/bug/field.html.tmpl b/template/en/default/bug/field.html.tmpl
index 58f1b0ccc..78a449990 100644
--- a/template/en/default/bug/field.html.tmpl
+++ b/template/en/default/bug/field.html.tmpl
@@ -97,6 +97,7 @@
</script>
[% CASE [ constants.FIELD_TYPE_SINGLE_SELECT
constants.FIELD_TYPE_MULTI_SELECT ] %]
+ <input type="hidden" id="[% field.name FILTER html %]_dirty">
<select id="[% field.name FILTER html %]"
name="[% field.name FILTER html %]"
[% IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]
@@ -121,6 +122,30 @@
[% END %]
[% FOREACH legal_value = legal_values %]
[% NEXT IF NOT legal_value.is_active AND NOT value.contains(legal_value.name).size %]
+
+ [%# Purpose: hide field values from those who can't change them %]
+ [% IF field.name.match("^cf_blocking_") OR
+ field.name.match("^cf_status_") OR
+ field.name.match("^cf_tracking_") OR
+ field.name == "resolution" %]
+ [% NEXT UNLESS bug.check_can_change_field(field.name, '---', legal_value.name) OR
+ value.contains(legal_value.name).size %]
+ [% END %]
+
+ [% IF field.name == "resolution" &&
+ legal_value.name != bug.resolution %]
+ [% r = legal_value.name %]
+ [% IF bug.user.canconfirm &&
+ !(bug.user.canedit || bug.user.isreporter) %]
+ [% NEXT IF r != "WORKSFORME" && r != "INCOMPLETE" %]
+ [% END %]
+ [% IF bug.user.isreporter &&
+ !(bug.user.canconfirm || bug.user.canedit) %]
+ [% NEXT IF r == "INCOMPLETE" %]
+ [% END %]
+ [% NEXT IF r == "EXPIRED" %]
+ [% END %]
+
<option value="[% legal_value.name FILTER html %]"
id="v[% legal_value.id FILTER html %]_
[%- field.name FILTER html %]"
@@ -173,11 +198,11 @@
[% IF Param('use_see_also') %]
<span id="container_showhide_[% field.name FILTER html %]"
class="bz_default_hidden">
- <a href="#" id="showhide_[% field.name FILTER html %]">(add)</a>
+ (<a href="#" id="showhide_[% field.name FILTER html %]">add</a>)
</span>
<div id="container_[% field.name FILTER html %]">
<label for="[% field.name FILTER html %]">
- <strong>Add [% terms.Bug %] URLs:</strong>
+ Add [% terms.Bug %] URLs:
</label><br>
<input type="text" id="[% field.name FILTER html %]" size="40"
class="text_input" name="[% field.name FILTER html %]">
diff --git a/template/en/default/bug/navigate.html.tmpl b/template/en/default/bug/navigate.html.tmpl
index 46b92aec4..56150bec3 100644
--- a/template/en/default/bug/navigate.html.tmpl
+++ b/template/en/default/bug/navigate.html.tmpl
@@ -29,12 +29,22 @@
<li>&nbsp;-&nbsp;<a href="show_bug.cgi?ctype=xml&amp;id=
[% bug.bug_id FILTER uri %]">XML</a></li>
<li>&nbsp;-&nbsp;<a href="enter_bug.cgi?cloned_bug_id=
- [% bug.bug_id FILTER uri %]">Clone This
+ [% bug.bug_id FILTER uri %]"
+ id="clone_bug">Clone This
[% terms.Bug %]</a></li>
[%# Links to more things users can do with this bug. %]
[% Hook.process("links") %]
<li>&nbsp;-&nbsp;<a href="#">Top of page </a></li>
- </ul>
+ </ul>
+ <script type="text/javascript">
+ YAHOO.util.Event.onDOMReady(function() {
+ init_clone_bug_menu(
+ YAHOO.util.Dom.get('clone_bug'),
+ '[% bug.bug_id FILTER js %]',
+ '[% bug.product FILTER js %]',
+ '[% bug.component FILTER js %]');
+ });
+ </script>
[% END %]
diff --git a/template/en/default/bug/process/bugmail.html.tmpl b/template/en/default/bug/process/bugmail.html.tmpl
index b0132a2fe..50f6e7aa8 100644
--- a/template/en/default/bug/process/bugmail.html.tmpl
+++ b/template/en/default/bug/process/bugmail.html.tmpl
@@ -26,7 +26,15 @@
[% PROCESS global/variables.none.tmpl %]
-<dl>
+[%# hide the recipient list by default from new users %]
+[% show_recipients =
+ user.settings.post_bug_submit_action.value == 'nothing'
+ || user.in_group('canconfirm')
+ || !user.can_see_bug(mailing_bugid)
+%]
+
+<dl id="bugmail_summary_[% mailing_bugid FILTER none %]"
+ [%~ ' class="bz_default_hidden"' UNLESS show_recipients %]>
[% PROCESS emails
description = "Email sent to"
names = sent_bugmail.sent
@@ -38,6 +46,27 @@
%]
</dl>
+[% IF !show_recipients %]
+ [% recipient_count = sent_bugmail.sent.size %]
+ <div id="bugmail_summary_placeholder_[% mailing_bugid FILTER none %]"
+ [%~ ' class="bz_default_hidden"' IF show_recipients %]>
+ [% IF recipient_count > 0 %]
+ Email sent to [% recipient_count FILTER html %]
+ recipient[% 's' UNLESS recipient_count == 1 %].
+ [% ELSE %]
+ No emails were sent.
+ [% END %]
+ (<a href="#" onclick="
+ YAHOO.util.Dom.removeClass(
+ 'bugmail_summary_[% mailing_bugid FILTER none %]',
+ 'bz_default_hidden');
+ YAHOO.util.Dom.addClass(
+ 'bugmail_summary_placeholder_[% mailing_bugid FILTER none %]',
+ 'bz_default_hidden');
+ return false;">show</a>)
+ </div>
+[% END %]
+
[%############################################################################%]
[%# Block for a set of email addresses #%]
[%############################################################################%]
diff --git a/template/en/default/bug/process/updates-disabled.html.tmpl b/template/en/default/bug/process/updates-disabled.html.tmpl
new file mode 100644
index 000000000..5ea84d476
--- /dev/null
+++ b/template/en/default/bug/process/updates-disabled.html.tmpl
@@ -0,0 +1,73 @@
+[%# The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is
+ # the Mozilla Foundation.
+ # Portions created by the Initial Developer are Copyright (C) 2011
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s): Byron Jones <glob@mozilla.com>
+ #
+ #%]
+[% PROCESS global/variables.none.tmpl %]
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>[% terms.Bugzilla %] - [% terms.Bug %] Updates Temporarily Suspended</title>
+<style type="text/css">
+body {
+ margin: 2em;
+ background-color: #455372;
+ color: #fff;
+ font-family: verdana, sans-serif;
+ font-size: small;
+}
+a {
+ color: #fff;
+ text-decoration: underline;
+}
+#buggie {
+ float: left;
+}
+#content {
+ margin-left: 100px;
+ max-width: 600px;
+}
+</style>
+</head>
+<body>
+<img src="images/buggie.png" id="buggie" alt="buggie">
+<div id="content">
+<h1>[% terms.Bug %] Updates Temporarily Suspended</h1>
+
+<p>
+We are currently adding a field to [% terms.Bugzilla %]. This requires us to
+prevent updates to [% terms.bugs %] for the duration of the database schema
+change to add the field (usually 3 to 5 minutes).
+</p>
+
+<p>
+<b>You should be able to leave this page open, wait a minute or two, then hit
+reload or refresh in your browser</b> (and OK any request to re-send the form
+data) to complete your [% terms.bug %] change. Once this maintenance is
+complete, your change will succeed and you won't get this page any more.
+</p>
+
+<p>
+Only updates to [% terms.bugs %] are being blocked by this page, any other
+activities in [% terms.Bugzilla %] are still fair game. <a href="index.cgi"
+target="_blank">Open [% terms.Bugzilla %] in a new tab/window</a> if you'd
+like, to continue working on other things while waiting.
+</p>
+</div>
+</body>
+</html>
diff --git a/template/en/default/bug/show-header.html.tmpl b/template/en/default/bug/show-header.html.tmpl
index 54570911d..ee1ecf6d2 100644
--- a/template/en/default/bug/show-header.html.tmpl
+++ b/template/en/default/bug/show-header.html.tmpl
@@ -31,24 +31,43 @@
[% filtered_desc = bug.short_desc FILTER html %]
[% subheader = filtered_desc %]
[% filtered_timestamp = bug.delta_ts FILTER time %]
-[% title = "$terms.Bug $bug.bug_id &ndash; $filtered_desc" %]
+[% title = "$terms.Bug $bug.bug_id &ndash; " %]
+[% IF bug.alias != '' %]
+ [% title = title _ "($bug.alias) " %]
+[% END %]
+[% title = title _ filtered_desc %]
[% header = "$terms.Bug&nbsp;$bug.bug_id" %]
[% header_addl_info = "Last modified: $filtered_timestamp" %]
[% yui = ['autocomplete', 'calendar'] %]
[% javascript_urls = [ "js/util.js", "js/field.js" ] %]
[% IF bug.defined %]
- [% unfiltered_title = "$terms.Bug $bug.bug_id – $bug.short_desc" %]
+ [% unfiltered_title = "$terms.Bug $bug.bug_id – " %]
+ [% IF bug.alias != '' %]
+ [% unfiltered_title = unfiltered_title _ "($bug.alias) " %]
+ [% END %]
+ [% unfiltered_title = unfiltered_title _ bug.short_desc %]
[% javascript = BLOCK %]
- if( !document.location.href.match(/show_bug\.cgi/) && history && history.replaceState ) {
- history.replaceState( null,
- "[% unfiltered_title FILTER js %]",
- "show_bug.cgi?id=[% bug.bug_id FILTER js %]" );
- document.title = "[% unfiltered_title FILTER js %]";
+ if (history && history.replaceState) {
+ if(!document.location.href.match(/show_bug\.cgi/)) {
+ history.replaceState( null,
+ "[% unfiltered_title FILTER js %]",
+ "show_bug.cgi?id=[% bug.bug_id FILTER js %]" );
+ document.title = "[% unfiltered_title FILTER js %]";
+ }
+ if (document.location.href.match(/show_bug\.cgi\?.*list_id=/)) {
+ var href = document.location.href;
+ href = href.replace(/[\?&]+list_id=(\d+|cookie)/, '');
+ history.replaceState(null, "[% unfiltered_title FILTER js %]", href);
+ }
}
+ YAHOO.util.Event.onDOMReady(function() {
+ initDirtyFieldTracking();
+ });
[% javascript FILTER none %]
[% END %]
[% END %]
-[% style_urls = [ "skins/standard/show_bug.css" ] %]
+[% style_urls = [ "skins/standard/show_bug.css",
+ "skins/custom/bug_groups.css" ] %]
[% doc_section = "bug_page.html" %]
[% bodyclasses = ['bz_bug',
"bz_status_$bug.bug_status",
diff --git a/template/en/default/bug/show-multiple.html.tmpl b/template/en/default/bug/show-multiple.html.tmpl
index 7c2b5345e..207b3ed86 100644
--- a/template/en/default/bug/show-multiple.html.tmpl
+++ b/template/en/default/bug/show-multiple.html.tmpl
@@ -192,6 +192,8 @@
[% USE Bugzilla %]
[% field_counter = 0 %]
[% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT IF cf_hidden_in_product(field.name, bug.product, bug.component) %]
+ [% NEXT IF cf_flag_disabled(field.name, bug) %]
[% field_counter = field_counter + 1 %]
[%# Odd-numbered fields get an opening <tr> %]
[% '<tr>' IF field_counter % 2 %]
diff --git a/template/en/default/bug/show.xml.tmpl b/template/en/default/bug/show.xml.tmpl
index dae207f26..cb323d229 100644
--- a/template/en/default/bug/show.xml.tmpl
+++ b/template/en/default/bug/show.xml.tmpl
@@ -20,8 +20,10 @@
#
#%]
[% PROCESS bug/time.html.tmpl %]
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
<?xml version="1.0" [% IF Param('utf8') %]encoding="UTF-8" [% END %]standalone="yes" ?>
-<!DOCTYPE bugzilla SYSTEM "[% urlbase FILTER html %]bugzilla.dtd">
+<!DOCTYPE bugzilla [% IF cgi.param('dtd') %][[% PROCESS pages/bugzilla.dtd.tmpl %]][% ELSE %]SYSTEM "[% urlbase FILTER xml %]page.cgi?id=bugzilla.dtd"[% END %]>
<bugzilla version="[% constants.BUGZILLA_VERSION %]"
urlbase="[% urlbase FILTER xml %]"
@@ -142,6 +144,7 @@
[% ELSIF field == "see_also" %]
[% val = val.name %]
[% END %]
+ [% NEXT IF cf_hidden_in_product(field.name, bug.product, bug.component) %]
<[% field %][% IF name != '' %] name="[% name FILTER xml %]"[% END -%]>
[%- val FILTER xml %]</[% field %]>
[% END %]
diff --git a/template/en/default/bug/time.html.tmpl b/template/en/default/bug/time.html.tmpl
index e070e7de0..c58675b96 100644
--- a/template/en/default/bug/time.html.tmpl
+++ b/template/en/default/bug/time.html.tmpl
@@ -18,7 +18,7 @@
# Contributor(s): Jeff Hedlund <jeff.hedlund@matrixsi.com>
#
#%]
-
+
[% BLOCK formattimeunit %]
[%# INTERFACE:
# time_unit: the number converting, converts to 2 decimal places
@@ -26,11 +26,7 @@
# 1 decimal place
#%]
[% time_unit = time_unit FILTER format('%.2f') %]
- [% IF time_unit.match('0\Z') %]
- [% time_unit FILTER format('%.1f') %]
- [% ELSE %]
- [% time_unit FILTER format('%.2f') %]
- [% END %]
+ [% time_unit.replace('0\Z', '') %]
[% END %]
[% BLOCK calculatepercentage %]
diff --git a/template/en/default/config.rdf.tmpl b/template/en/default/config.rdf.tmpl
index 15f784ce8..5686d138b 100644
--- a/template/en/default/config.rdf.tmpl
+++ b/template/en/default/config.rdf.tmpl
@@ -168,12 +168,12 @@
<bz:component rdf:about="[% escaped_urlbase %]component.cgi?name=[% component.name FILTER uri
%]&amp;product=[% product.name FILTER uri %]">
<bz:name>[% component.name FILTER html %]</bz:name>
+ <bz:is_active>[% component.is_active FILTER html %]</bz:is_active>
[% IF show_flags %]
<bz:flag_types>
<Seq>
[% flag_types = component.flag_types.bug.merge(component.flag_types.attachment) %]
[% FOREACH flag_type = flag_types %]
- [% NEXT UNLESS flag_type.is_active %]
[% all_visible_flag_types.${flag_type.id} = flag_type %]
<li resource="[% escaped_urlbase %]flag.cgi?id=[% flag_type.id FILTER uri
%]&amp;name=[% flag_type.name FILTER uri %]" />
@@ -195,6 +195,7 @@
<li>
<bz:version rdf:about="[% escaped_urlbase %]version.cgi?name=[% version.name FILTER uri %]">
<bz:name>[% version.name FILTER html %]</bz:name>
+ <bz:is_active>[% version.is_active FILTER html %]</bz:is_active>
</bz:version>
</li>
[% END %]
@@ -210,6 +211,7 @@
<li>
<bz:target_milestone rdf:about="[% escaped_urlbase %]milestone.cgi?name=[% milestone.name FILTER uri %]">
<bz:name>[% milestone.name FILTER html %]</bz:name>
+ <bz:is_active>[% milestone.is_active FILTER html %]</bz:is_active>
</bz:target_milestone>
</li>
[% END %]
diff --git a/template/en/default/email/bugmail-header.txt.tmpl b/template/en/default/email/bugmail-header.txt.tmpl
index 94559a942..7e871c4f8 100644
--- a/template/en/default/email/bugmail-header.txt.tmpl
+++ b/template/en/default/email/bugmail-header.txt.tmpl
@@ -23,25 +23,17 @@
[% PROCESS "global/field-descs.none.tmpl" %]
[% PROCESS "global/reason-descs.none.tmpl" %]
[% isnew = bug.lastdiffed ? 0 : 1 %]
+[% show_new = isnew
+ && (to_user.settings.bugmail_new_prefix.value == 'on') %]
From: [% Param('mailfrom') %]
To: [% to_user.email %]
-Subject: [[% terms.Bug %] [%+ bug.id %]] [% 'New: ' IF isnew %][%+ bug.short_desc %]
+Subject: [[% terms.Bug %] [%+ bug.id %]] [% 'New: ' IF show_new %][%+ bug.short_desc %]
Date: [% date %]
X-Bugzilla-Reason: [% reasonsheader %]
X-Bugzilla-Type: [% isnew ? 'new' : 'changed' %]
X-Bugzilla-Watch-Reason: [% reasonswatchheader %]
-[% IF Param('useclassification') %]
-X-Bugzilla-Classification: [% bug.classification %]
-[% END %]
-X-Bugzilla-Product: [% bug.product %]
-X-Bugzilla-Component: [% bug.component %]
-X-Bugzilla-Keywords: [% bug.keywords %]
-X-Bugzilla-Severity: [% bug.bug_severity %]
-X-Bugzilla-Who: [% changer.login %]
-X-Bugzilla-Status: [% bug.bug_status %]
-X-Bugzilla-Priority: [% bug.priority %]
-X-Bugzilla-Assigned-To: [% bug.assigned_to.login %]
-X-Bugzilla-Target-Milestone: [% bug.target_milestone %]
+[%+ INCLUDE "email/header-common.txt.tmpl" %]
X-Bugzilla-Changed-Fields: [% changedfields.join(" ") %]
+X-Bugzilla-Changed-Field-Names: [% changedfieldnames.join(" ") %]
[%+ threadingmarker %]
diff --git a/template/en/default/email/bugmail.html.tmpl b/template/en/default/email/bugmail.html.tmpl
index d52fe6306..88c935d87 100644
--- a/template/en/default/email/bugmail.html.tmpl
+++ b/template/en/default/email/bugmail.html.tmpl
@@ -40,9 +40,24 @@
</div>
[% END %]
</p>
+
+ [% IF referenced_bugs.size %]
+ <hr>
+ <span>Referenced [% terms.Bugs %]:</span>
+
+ <ul>
+ [% FOREACH ref = referenced_bugs %]
+ <li>
+ [<a href="[% urlbase FILTER html %]show_bug.cgi?id=[% ref.id FILTER none %]">
+ [% terms.Bug %]&nbsp;[% ref.id FILTER none %]</a>] [% ref.short_desc FILTER html %]
+ </li>
+ [% END %]
+ </ul>
+ [% END %]
+
<hr>
<span>You are receiving this mail because:</span>
-
+
<ul>
[% FOREACH reason = reasons %]
[% IF reason_descs.$reason %]
diff --git a/template/en/default/email/bugmail.txt.tmpl b/template/en/default/email/bugmail.txt.tmpl
index 0b349fb15..fed0565c7 100644
--- a/template/en/default/email/bugmail.txt.tmpl
+++ b/template/en/default/email/bugmail.txt.tmpl
@@ -34,6 +34,15 @@
[% END %]
[%+ comment.body_full({ is_bugmail => 1, wrap => 1 }) %]
[% END %]
+[% IF referenced_bugs.size %]
+
+Referenced [% terms.Bugs %]:
+
+[% FOREACH ref = referenced_bugs %]
+[%+ urlbase %]show_bug.cgi?id=[% ref.id %]
+[%+ "[" _ terms.Bug _ " " _ ref.id _ "] " _ ref.short_desc FILTER wrap_comment(76) %]
+[% END %]
+[% END %]
-- [%# Protect the trailing space of the signature marker %]
You are receiving this mail because:
diff --git a/template/en/default/email/header-common.txt.tmpl b/template/en/default/email/header-common.txt.tmpl
new file mode 100644
index 000000000..3f3b7d373
--- /dev/null
+++ b/template/en/default/email/header-common.txt.tmpl
@@ -0,0 +1,24 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+[% IF Param('useclassification') %]
+X-Bugzilla-Classification: [% bug.classification %]
+[% END %]
+X-Bugzilla-ID: [% bug.id %]
+X-Bugzilla-Product: [% bug.product %]
+X-Bugzilla-Component: [% bug.component %]
+X-Bugzilla-Version: [% bug.version %]
+X-Bugzilla-Keywords: [% bug.keywords %]
+X-Bugzilla-Severity: [% bug.bug_severity %]
+X-Bugzilla-Who: [% changer.login %]
+X-Bugzilla-Status: [% bug.bug_status %]
+X-Bugzilla-Resolution: [% bug.resolution %]
+X-Bugzilla-Priority: [% bug.priority %]
+X-Bugzilla-Assigned-To: [% bug.assigned_to.login %]
+X-Bugzilla-Target-Milestone: [% bug.target_milestone %]
+X-Bugzilla-Flags:[% FOREACH flag = bug.flags %] [%+ flag.name %][% flag.status %][% END %]
+X-Bugzilla-OS: [% bug.op_sys %]
diff --git a/template/en/default/email/lockout.txt.tmpl b/template/en/default/email/lockout.txt.tmpl
index ac6525779..94e9c74cb 100644
--- a/template/en/default/email/lockout.txt.tmpl
+++ b/template/en/default/email/lockout.txt.tmpl
@@ -22,10 +22,10 @@
From: [% Param('mailfrom') %]
To: [% Param('maintainer') %]
-Subject: [[% terms.Bugzilla %]] Account Lock-Out: [% locked_user.login %] ([% attempts.0.ip_addr %])
+Subject: [[% terms.Bugzilla %]] Account Lock-Out: [% locked_user.login %] ([% address %])
X-Bugzilla-Type: admin
-The IP address [% attempts.0.ip_addr %] failed too many login attempts (
+The address [% address %] failed too many login attempts (
[%- constants.MAX_LOGIN_ATTEMPTS +%]) for
the account [% locked_user.login %].
diff --git a/template/en/default/filterexceptions.pl b/template/en/default/filterexceptions.pl
index 691241c9c..08757cfe7 100644
--- a/template/en/default/filterexceptions.pl
+++ b/template/en/default/filterexceptions.pl
@@ -52,7 +52,6 @@
],
'flag/list.html.tmpl' => [
- 'flag.id',
'flag.status',
'type.id',
],
@@ -219,7 +218,6 @@
'bug/comments.html.tmpl' => [
'comment.id',
- 'comment.count',
'bug.bug_id',
],
@@ -282,8 +280,7 @@
'bug/time.html.tmpl' => [
- 'time_unit FILTER format(\'%.1f\')',
- 'time_unit FILTER format(\'%.2f\')',
+ "time_unit.replace('0\\Z', '')",
'(act / (act + rem)) * 100
FILTER format("%d")',
],
@@ -321,7 +318,6 @@
'attachment/edit.html.tmpl' => [
'attachment.id',
'attachment.bug_id',
- 'a',
'editable_or_hide',
],
diff --git a/template/en/default/flag/list.html.tmpl b/template/en/default/flag/list.html.tmpl
index 4467e81ce..8de9955ea 100644
--- a/template/en/default/flag/list.html.tmpl
+++ b/template/en/default/flag/list.html.tmpl
@@ -18,7 +18,7 @@
# Contributor(s): Myk Melez <myk@mozilla.org>
#%]
-[% IF user.id AND !read_only_flags %]
+[% IF user.id && !read_only_flags && (!bug || bug.check_can_change_field('flagtypes.name', 0, 1)) %]
[%# We list flags by looping twice over the flag types relevant for the bug.
# In the first loop, we display existing flags and then, for active types,
@@ -51,73 +51,13 @@
[%-# Step 1a: Display existing flag(s). %]
[% FOREACH flag = type.flags %]
- <tr>
- <td>
- <span title="[% flag.setter.identity FILTER html %]">[% flag.setter.nick FILTER html %]</span>:
- </td>
- <td>
- <label title="[% type.description FILTER html %]"
- for="flag-[% flag.id %]">
- [%- type.name FILTER html FILTER no_break -%]</label>
- </td>
- <td>
- <select id="flag-[% flag.id %]" name="flag-[% flag.id %]"
- title="[% type.description FILTER html %]"
- onchange="toggleRequesteeField(this);"
- class="flag_select flag_type-[% type.id %]">
- [%# Only display statuses the user is allowed to set. %]
- [% IF user.can_request_flag(type) || flag.setter_id == user.id %]
- <option value="X"></option>
- [% END %]
- [% IF type.is_active %]
- [% IF (type.is_requestable && user.can_request_flag(type)) || flag.status == "?" %]
- <option value="?" [% "selected" IF flag.status == "?" %]>?</option>
- [% END %]
- [% IF user.can_set_flag(type) || flag.status == "+" %]
- <option value="+" [% "selected" IF flag.status == "+" %]>+</option>
- [% END %]
- [% IF user.can_set_flag(type) || flag.status == "-" %]
- <option value="-" [% "selected" IF flag.status == "-" %]>-</option>
- [% END %]
- [% ELSE %]
- <option value="[% flag.status %]" selected="selected">[% flag.status %]</option>
- [% END %]
- </select>
- </td>
- [% IF any_flags_requesteeble %]
- <td>
- [% IF (type.is_active && type.is_requestable && type.is_requesteeble) || flag.requestee %]
- <span style="white-space: nowrap;">
- [% SET flag_custom_list = [] %]
- [% IF Param('usemenuforusers') %]
- [% flag_custom_list = flag.type.grant_list %]
- [% IF !(type.is_active && type.is_requestable && type.is_requesteeble) %]
- [%# We are here only because there was already a requestee. In this case,
- the only valid action is to remove the requestee or leave it alone;
- nothing else. %]
- [% flag_custom_list = [flag.requestee] %]
- [% END %]
- [% END %]
- [% INCLUDE global/userselect.html.tmpl
- name => "requestee-$flag.id"
- id => "requestee-$flag.id"
- value => flag.requestee.login
- multiple => 0
- emptyok => 1
- classes => ["requestee"]
- custom_userlist => flag_custom_list
- %]
- </span>
- [% END %]
- </td>
- [% END %]
- </tr>
+ [% PROCESS flag_row flag = flag type = type %]
[% END -%]
+ [% SET flag = "" %]
[%-# Step 1b: Display UI for setting flag. %]
[% IF (!type.flags || type.flags.size == 0) && type.is_active %]
-
- [% PROCESS flag_row first_cell_empty = 1 addl_text = "" %]
+ [% PROCESS flag_row type = type %]
[% END %]
[% END %]
@@ -125,11 +65,12 @@
[% FOREACH type = flag_types %]
[% NEXT UNLESS type.flags && type.flags.size > 0 && type.is_multiplicable && type.is_active %]
[% IF !separator_displayed %]
+ <tbody class="bz_flag_type">
<tr><td colspan="3"><hr></td></tr>
- [% separator_displayed = 1 %]
+ </tbody>
+ [% separator_displayed = 1 %]
[% END %]
-
- [% PROCESS flag_row first_cell_empty = 0 addl_text = "addl." %]
+ [% PROCESS flag_row type = type addl_text = "addl." %]
[% END %]
</table>
@@ -159,58 +100,82 @@
[% END %]
[% END %]
-[%# Display a table row for unset flags %]
+[%# Display a table row for flags %]
[% BLOCK flag_row %]
- <tr>
- [% IF first_cell_empty %]
- <td>&nbsp;</td>
- <td>
- [% ELSE %]
- <td colspan="2">
- [% END %]
-
- [% addl_text FILTER html %]
- <label title="[% type.description FILTER html %]" for="flag_type-[% type.id %]">
- [%- type.name FILTER html FILTER no_break %]</label>
- </td>
- <td>
- <select id="flag_type-[% type.id %]" name="flag_type-[% type.id %]"
- title="[% type.description FILTER html %]"
- [% " disabled=\"disabled\"" UNLESS (type.is_requestable && user.can_request_flag(type)) || user.can_set_flag(type) %]
- onchange="toggleRequesteeField(this);"
- class="flag_select flag_type-[% type.id %]">
- <option value="X"></option>
- [% IF type.is_requestable && user.can_request_flag(type) %]
- <option value="?">?</option>
- [% END %]
- [% IF user.can_set_flag(type) %]
- <option value="+">+</option>
- <option value="-">-</option>
+ [% SET fid = flag ? "flag-$flag.id" : "flag_type-$type.id" %]
+ <tbody[% ' class="bz_flag_type"' IF !flag %]>
+ <tr>
+ <td>
+ [% IF flag %]
+ <span title="[% flag.setter.identity FILTER html %]">[% flag.setter.nick FILTER html %]</span>:
+ [% ELSE %]
+ [% addl_text FILTER html %]
[% END %]
- </select>
- </td>
- [% IF any_flags_requesteeble %]
+ </td>
<td>
- [% IF type.is_requestable && type.is_requesteeble %]
- <span style="white-space: nowrap;">
- [% SET grant_list = [] %]
- [% IF Param('usemenuforusers') %]
- [% grant_list = type.grant_list %]
- [% END %]
- [% INCLUDE global/userselect.html.tmpl
- name => "requestee_type-$type.id"
- id => "requestee_type-$type.id"
- multiple => type.is_multiplicable * 3
- emptyok => !type.is_multiplicable
- value => ""
- custom_userlist => grant_list
- classes => ["requestee"]
- %]
-
- </span>
+ <label title="[% type.description FILTER html %]" for="[% fid FILTER html %]">
+ [%- type.name FILTER html FILTER no_break -%]</label>
+ </td>
+ <td>
+ <input type="hidden" id="[% fid FILTER html %]_dirty">
+ <select id="[% fid FILTER html %]" name="[% fid FILTER html %]"
+ [% IF !flag && !((type.is_requestable && user.can_request_flag(type)) || user.can_set_flag(type)) %]
+ disabled="disabled"
+ [% END %]
+ title="[% type.description FILTER html %]"
+ onchange="toggleRequesteeField(this);"
+ class="flag_select flag_type-[% type.id %]">
+ [%# Only display statuses the user is allowed to set. %]
+ [% IF !flag || user.can_request_flag(type) || flag.setter_id == user.id %]
+ <option value="X"></option>
+ [% END %]
+ [% IF type.is_active %]
+ [% IF (type.is_requestable && user.can_request_flag(type)) || (flag && flag.status == "?") %]
+ <option value="?" [% "selected" IF flag && flag.status == "?" %]>?</option>
+ [% END %]
+ [% IF user.can_set_flag(type) || (flag && flag.status == "+") %]
+ <option value="+" [% "selected" IF flag && flag.status == "+" %]>+</option>
+ [% END %]
+ [% IF user.can_set_flag(type) || (flag && flag.status == "-") %]
+ <option value="-" [% "selected" IF flag && flag.status == "-" %]>-</option>
+ [% END %]
+ [% ELSE %]
+ <option value="[% flag.status %]" selected="selected">[% flag.status %]</option>
[% END %]
+ </select>
</td>
- [% END %]
- </tr>
+ [% IF any_flags_requesteeble %]
+ <td>
+ [% IF (type.is_active && type.is_requestable && type.is_requesteeble) || (flag && flag.requestee) %]
+ <span style="white-space: nowrap;">
+ [% SET grant_list = [] %]
+ [% IF Param('usemenuforusers') %]
+ [% grant_list = type.grant_list %]
+ [% IF flag && !(type.is_active && type.is_requestable && type.is_requesteeble) %]
+ [%# We are here only because there was already a requestee. In this case,
+ the only valid action is to remove the requestee or leave it alone;
+ nothing else. %]
+ [% grant_list = [flag.requestee] %]
+ [% END %]
+ [% END %]
+ [% SET flag_name = flag ? "requestee-$flag.id" : "requestee_type-$type.id" %]
+ [% SET flag_requestee = (flag && flag.requestee) ? flag.requestee.login : '' %]
+ [% SET flag_multiple = flag ? 0 : type.is_multiplicable * 3 %]
+ [% SET flag_empty_ok = flag ? 1 : !type.is_multiplicable %]
+ [% INCLUDE global/userselect.html.tmpl
+ name => flag_name
+ id => flag_name
+ value => flag_requestee
+ multiple => flag_multiple
+ emptyok => flag_empty_ok
+ classes => ["requestee"]
+ custom_userlist => grant_list
+ %]
+ </span>
+ [% END %]
+ </td>
+ [% END %]
+ </tr>
+ </tbody>
[% END %]
diff --git a/template/en/default/global/code-error.html.tmpl b/template/en/default/global/code-error.html.tmpl
index 24e46fb14..704d3ad16 100644
--- a/template/en/default/global/code-error.html.tmpl
+++ b/template/en/default/global/code-error.html.tmpl
@@ -262,7 +262,7 @@
Flags cannot be set for objects of type [% caller FILTER html %].
They can only be set for [% terms.bugs %] and attachments.
- [% ELSIF error == "flag_requestee_disabled" %]
+ [% ELSIF error == "flag_type_requestee_disabled" %]
[% title = "Flag not Requestable from Specific Person" %]
You can't ask a specific person for
<em>[% type.name FILTER html %]</em>.
@@ -506,31 +506,23 @@
admindocslinks = admindocslinks
%]
-<tt>
- <p>
- [% terms.Bugzilla %] has suffered an internal error. Please save this page and send
- it to [% Param("maintainer") %] with details of what you were doing at
- the time this message appeared.
- </p>
- <script type="text/javascript"> <!--
- document.write("<p>URL: " +
- document.location.href.replace(/&/g,"&amp;")
- .replace(/</g,"&lt;")
- .replace(/>/g,"&gt;") + "</p>");
- // -->
- </script>
-</tt>
-
-<table cellpadding="20">
- <tr>
- <td id="error_msg" class="throw_error">
- [% error_message FILTER none %]
- </td>
- </tr>
-</table>
+[%# return the generated error_message for arecibo %]
+[% processed.error_message = error_message %]
+
+<p>
+ [% terms.Bugzilla %] has suffered an internal error:
+</p>
-<p>Traceback:</p>
-<pre>[% traceback FILTER html %]</pre>
+<p class="throw_error">
+ [% error_message FILTER none %]
+</p>
+
+[% IF maintainers_notified %]
+<p>
+ The [% terms.Bugzilla %] maintainers have been notified of this error
+ [#[% uid FILTER html %]].
+</p>
+[% END %]
[% IF variables %]
<pre>
diff --git a/template/en/default/global/common-links.html.tmpl b/template/en/default/global/common-links.html.tmpl
index 769d41e7e..ec8608eed 100644
--- a/template/en/default/global/common-links.html.tmpl
+++ b/template/en/default/global/common-links.html.tmpl
@@ -55,6 +55,8 @@
[% END %]
[%-# Work around FF bug: keep this on one line %]</li>
+ [% Hook.process('action-links') %]
+
[% IF user.login %]
<li><span class="separator">| </span><a href="userprefs.cgi">Preferences</a></li>
[% IF user.in_group('tweakparams') || user.in_group('editusers') || user.can_bless
diff --git a/template/en/default/global/field-descs.none.tmpl b/template/en/default/global/field-descs.none.tmpl
index 3e86e9bad..46fbc6d31 100644
--- a/template/en/default/global/field-descs.none.tmpl
+++ b/template/en/default/global/field-descs.none.tmpl
@@ -49,7 +49,9 @@
"changedto" => "changed to",
"changedby" => "changed by",
"matches" => "matches",
- "notmatches" => "does not match",
+ "notmatches" => "does not match",
+ "isempty" => "is empty",
+ "isnotempty" => "is not empty",
} %]
[% field_types = { ${constants.FIELD_TYPE_UNKNOWN} => "Unknown Type",
diff --git a/template/en/default/global/footer.html.tmpl b/template/en/default/global/footer.html.tmpl
index 661f8afe6..29d17bccd 100644
--- a/template/en/default/global/footer.html.tmpl
+++ b/template/en/default/global/footer.html.tmpl
@@ -24,8 +24,6 @@
# global/useful-links.html.tmpl.
#%]
-[% INCLUDE "global/help.html.tmpl" %]
-
</div>
[%# Migration note: below this point, this file corresponds to the old Param
diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl
index 0dffcb5de..1abd7e8c7 100644
--- a/template/en/default/global/header.html.tmpl
+++ b/template/en/default/global/header.html.tmpl
@@ -110,12 +110,8 @@
[% SET yui = yui_resolve_deps(yui, yui_deps) %]
[% SET css_sets = css_files(style_urls, yui, yui_css) %]
- [%# CSS cascade, part 1: Standard Bugzilla stylesheet set (persistent).
- # Always present.
- #%]
- [%# This allows people to switch back to the "Classic" skin if they
- # are in another skin.
- #%]
+ [%# CSS cascade, parts 1 & 2: YUI & Standard Bugzilla stylesheet set (persistent).
+ # Always present. %]
<link href="[% 'skins/standard/global.css' FILTER mtime FILTER html %]"
rel="alternate stylesheet"
title="[% setting_descs.standard FILTER html %]">
@@ -123,22 +119,12 @@
[% PROCESS format_css_link css_set_name = 'standard' %]
[% END %]
- [%# CSS cascade, part 2 & 3: Third-party stylesheet set (selected and
- # selectable). All third-party skins are present as alternate
- # stylesheets, even if they are not currently in use.
- #%]
+ [%# CSS cascade, part 3: Third-party stylesheet set, per user prefs. %]
[% FOREACH style_url = css_sets.skin %]
[% PROCESS format_css_link css_set_name = user.settings.skin.value %]
[% END %]
- [% FOREACH alternate_skin = css_sets.alternate.keys %]
- [% FOREACH style_url = css_sets.alternate.$alternate_skin %]
- [% PROCESS format_css_link css_set_name = alternate_skin %]
- [% END %]
- [% END %]
-
- [%# CSS cascade, part 4: page-specific styles.
- #%]
+ [%# CSS cascade, part 4: page-specific styles. %]
[% IF style %]
<style type="text/css">
[% style %]
@@ -239,8 +225,7 @@
[%# Required for the 'Autodiscovery' feature in Firefox 2 and IE 7. %]
<link rel="search" type="application/opensearchdescription+xml"
- title="[% terms.Bugzilla %]" href="./search_plugin.cgi">
- <link rel="shortcut icon" href="images/favicon.ico" >
+ title="[% terms.BugzillaTitle %]" href="./search_plugin.cgi">
[% Hook.process("additional_header") %]
</head>
@@ -265,7 +250,7 @@
<table border="0" cellspacing="0" cellpadding="0" id="titles">
<tr>
<td id="title">
- <p>[% terms.Bugzilla %]
+ <p>[% terms.BugzillaTitle %]
[% " &ndash; $header" IF header %]</p>
</td>
@@ -311,7 +296,7 @@
[% END %]
[% IF message %]
-<div id="message">[% message %]</div>
+ <div id="message">[% message %]</div>
[% END %]
[% BLOCK format_css_link %]
@@ -323,26 +308,15 @@
#%]
[% END %]
- [% IF css_set_name == 'standard'
- OR css_set_name == user.settings.skin.value
- %]
- [% SET css_rel = 'stylesheet' %]
- [% SET css_set_display_name = setting_descs.${user.settings.skin.value}
- || user.settings.skin.value %]
- [% ELSE %]
- [% SET css_rel = 'alternate stylesheet' %]
- [% SET css_set_display_name = setting_descs.$css_set_name || css_set_name %]
- [% END %]
-
[% IF css_set_name == 'standard' %]
[% SET css_title_link = '' %]
[% ELSE %]
[% css_title_link = BLOCK ~%]
- title="[% css_set_display_name FILTER html %]"
+ title="[% setting_descs.${user.settings.skin.value} || user.settings.skin.value FILTER html %]"
[% END %]
[% END %]
- <link href="[% style_url FILTER html %]" rel="[% css_rel FILTER none %]"
+ <link href="[% style_url FILTER html %]" rel="stylesheet"
type="text/css" [% css_title_link FILTER none %]>
[% '<![endif]-->' IF style_url.match('/IE-fixes\.css') %]
diff --git a/template/en/default/global/setting-descs.none.tmpl b/template/en/default/global/setting-descs.none.tmpl
index a0b11f048..37d81039e 100644
--- a/template/en/default/global/setting-descs.none.tmpl
+++ b/template/en/default/global/setting-descs.none.tmpl
@@ -52,6 +52,8 @@
"email_format" => "Preferred email format",
"html" => "HTML",
"text_only" => "Text Only",
+ "bugmail_new_prefix" => "Add 'New:' to subject line of email sent when a new $terms.bug is filed",
+ "requestee_cc" => "Automatically add me to the CC list of $terms.bugs I am requested to review",
}
%]
diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl
index 2341cd58f..d53708409 100644
--- a/template/en/default/global/user-error.html.tmpl
+++ b/template/en/default/global/user-error.html.tmpl
@@ -160,6 +160,8 @@
use
[% ELSIF action == "approve" %]
approve
+ [% ELSIF action == "admin_activity" %]
+ view admin activity for
[% ELSE %]
[%+ Hook.process('auth_failure_action') %]
[% END %]
@@ -270,6 +272,7 @@
<li>A ticket in a Trac installation.</li>
<li>A b[% %]ug in a MantisBT installation.</li>
<li>A b[% %]ug on sourceforge.net.</li>
+ <li>An issue on github.com.</li>
</ul>
[% ELSIF reason == 'id' %]
There is no valid [% terms.bug %] id in that URL.
@@ -618,6 +621,11 @@
<br>Alternately, if your attachment is an image, you could convert
it to a compressible format like JPG or PNG and try again.
+ [% ELSIF error == "flag_requestee_disabled" %]
+ [% title = "Flag Requestee Disabled" %]
+ You can't ask <em>[% requestee.identity FILTER html %]</em> because that
+ account is disabled.
+
[% ELSIF error == "flag_requestee_needs_privs" %]
[% title = "Flag Requestee Needs Privileges" %]
[% requestee.identity FILTER html %] does not have permission to set the
@@ -1350,6 +1358,40 @@
[% END %]
</ul>
+ [% ELSIF error == "password_not_complex" %]
+ [% title = "Password Fails Requirements" %]
+ [% passregex = Param('password_complexity') %]
+ Password must contain at least one:
+ <ul>
+ [% IF passregex.search('letters') %]
+ <li>UPPERCASE letter</li>
+ <li>lowercase letter</li>
+ [% END %]
+ [% IF passregex.search('numbers') %]
+ <li>digit</li>
+ [% END %]
+ [% IF passregex.search('specialchars') %]
+ <li>special character</li>
+ [% END %]
+ </ul>
+
+ [% ELSIF error == "password_not_complex" %]
+ [% title = "Password Fails Requirements" %]
+ [% passregex = Param('password_complexity') %]
+ Password must contain at least one:
+ <ul>
+ [% IF passregex.search('letters') %]
+ <li>UPPERCASE letter</li>
+ <li>lowercase letter</li>
+ [% END %]
+ [% IF passregex.search('numbers') %]
+ <li>digit</li>
+ [% END %]
+ [% IF passregex.search('specialchars') %]
+ <li>special character</li>
+ [% END %]
+ </ul>
+
[% ELSIF error == "product_access_denied" %]
[% title = "Product Access Denied" %]
Either the product
@@ -1538,6 +1580,17 @@
and the "matches" search can only be used with the "content"
field.
+ [% ELSIF error == "search_grouped_field_invalid" %]
+ [% terms.Bugzilla %] does not support using the
+ "[%+ field_descs.$field FILTER html %]" ([% field FILTER html %])
+ field with grouped search conditions.
+
+ [% ELSIF error == "search_grouped_invalid_nesting" %]
+ You cannot nest clauses within grouped search conditions.
+
+ [% ELSIF error == "search_grouped_field_mismatch" %]
+ All conditions under a groups search must use the same field.
+
[% ELSIF error == "search_field_operator_invalid" %]
[% terms.Bugzilla %] does not support using the
"[%+ field_descs.$field FILTER html %]" ([% field FILTER html %])
@@ -1707,6 +1760,11 @@
Sorry, but you are not allowed to (un)mark comments or attachments
as private.
+ [% ELSIF error == "webdot_too_large" %]
+ [% title = "Dependency Graph Too Large" %]
+ The dependency graph contains too many [% terms.bugs %] to display (more
+ than [% constants.MAX_WEBDOT_BUGS FILTER html %] [%+ terms.bugs %]).
+
[% ELSIF error == "wrong_token_for_cancelling_email_change" %]
[% title = "Wrong Token" %]
That token cannot be used to cancel an email address change.
@@ -1764,6 +1822,8 @@
[% error_message FILTER none %]
[% END %]
[% END %]
+
+ [% Hook.process('error_message') %]
[% END %]
[%# We only want HTML error messages for ERROR_MODE_WEBPAGE %]
diff --git a/template/en/default/global/user.html.tmpl b/template/en/default/global/user.html.tmpl
index df902b451..4f9b8a41b 100644
--- a/template/en/default/global/user.html.tmpl
+++ b/template/en/default/global/user.html.tmpl
@@ -27,6 +27,10 @@
[% FILTER collapse %]
[% IF user.id %]
<a class="email" href="mailto:[% who.email FILTER html %]"
+ [% IF who.id && user.in_group('canconfirm') %]
+ onclick="return show_usermenu(event, [% who.id FILTER none %], '[% who.email FILTER js %]',
+ [% IF (user.in_group('editusers') || user.bless_groups.size > 0) %]true[% ELSE %]false[% END %]);"
+ [% END %]
title="[% who.identity FILTER html %]">
[%- END -%]
[% IF who.name %]
diff --git a/template/en/default/index.html.tmpl b/template/en/default/index.html.tmpl
index 5b9237aa1..29bc9adb6 100644
--- a/template/en/default/index.html.tmpl
+++ b/template/en/default/index.html.tmpl
@@ -125,30 +125,20 @@ YAHOO.util.Event.onDOMReady(onLoadActions);
<td>
<h1 id="welcome"> Welcome to [% terms.Bugzilla %]</h1>
<div class="intro">[% Hook.process('intro') %]</div>
-
- <div class="bz_common_actions">
- <ul>
- <li>
- <a id="enter_bug" href="enter_bug.cgi"><span>File
- [%= terms.aBug %]</span></a>
- </li>
- <li>
- <a id="query" href="query.cgi"><span>Search</span></a>
- </li>
- <li>
- <a id="account"
- [% IF user.id %]
- href="userprefs.cgi"><span>User Preferences</span></a>
- [% ELSIF Param('createemailregexp')
- && user.authorizer.user_can_create_account
- %]
- href="createaccount.cgi"><span>Open a New Account</span></a>
- [% ELSE %]
- href="?GoAheadAndLogIn=1"><span>Log In</span></a>
- [% END %]
- </li>
- </ul>
- </div>
+ <a id="enter_bug" class="bz_common_actions"
+ href="enter_bug.cgi"><span>File [% terms.aBug %]</span></a>
+ <a id="query" class="bz_common_actions"
+ href="query.cgi"><span>Search</span></a>
+ <a id="account" class="bz_common_actions"
+ [% IF user.id %]
+ href="userprefs.cgi"><span>User Preferences</span></a>
+ [% ELSIF Param('createemailregexp')
+ && user.authorizer.user_can_create_account
+ %]
+ href="createaccount.cgi"><span>Open a New Account</span></a>
+ [% ELSE %]
+ href="?GoAheadAndLogIn=1"><span>Log In</span></a>
+ [% END %]
<form id="quicksearchForm" name="quicksearchForm" action="buglist.cgi"
onsubmit="return checkQuicksearch(this);">
diff --git a/template/en/default/list/edit-multiple.html.tmpl b/template/en/default/list/edit-multiple.html.tmpl
index 92e578e8f..9ff95aad5 100644
--- a/template/en/default/list/edit-multiple.html.tmpl
+++ b/template/en/default/list/edit-multiple.html.tmpl
@@ -282,10 +282,12 @@
[% USE Bugzilla %]
[%# Show all legal values and all fields, ignoring visibility controls. %]
- [% bug = 0 %]
+ [% bug = default.defined ? default : 0 %]
[% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT IF cf_hidden_in_product(field.name, one_product, components) %]
<tr>
- [% PROCESS bug/field.html.tmpl value = dontchange
+ [% PROCESS bug/field.html.tmpl bug = default
+ value = dontchange
editable = 1
allow_dont_change = 1 %]
</tr>
@@ -427,6 +429,7 @@
[% FOREACH r = resolutions %]
[% NEXT IF !r %]
[% NEXT IF r == "DUPLICATE" || r == "MOVED" %]
+ [% NEXT IF r == "EXPIRED" AND user.login != "gerv@mozilla.org" %]
<option value="[% r FILTER html %]">[% display_value("resolution", r) FILTER html %]</option>
[% END %]
</select>
diff --git a/template/en/default/list/list.html.tmpl b/template/en/default/list/list.html.tmpl
index 4eeff5e64..cda06ac21 100644
--- a/template/en/default/list/list.html.tmpl
+++ b/template/en/default/list/list.html.tmpl
@@ -42,10 +42,11 @@
[%# Page Header #%]
[%############################################################################%]
+[% url_filtered_title = title FILTER uri %]
[% PROCESS global/header.html.tmpl
title = title
style = style
- atomlink = "buglist.cgi?$urlquerypart&title=$title&ctype=atom"
+ atomlink = "buglist.cgi?$urlquerypart&title=$url_filtered_title&ctype=atom"
yui = [ 'autocomplete', 'calendar' ]
javascript_urls = [ "js/util.js", "js/field.js" ]
style_urls = [ "skins/standard/buglist.css" ]
@@ -58,10 +59,16 @@
</span>
[% IF debug %]
- <p class="bz_query">[% query FILTER html %]</p>
- [% IF query_explain.defined %]
- <pre class="bz_query_explain">[% query_explain FILTER html %]</pre>
- [% END %]
+ <div class="bz_query_debug">
+ <p>Total execution time: [% query_time FILTER html %] seconds</p>
+ [% FOREACH query = queries %]
+ <p>[% query.sql FILTER html %]</p>
+ <p>Execution time: [% query.time FILTER html %] seconds</p>
+ [% IF query.explain %]
+ <pre>[% query.explain FILTER html %]</pre>
+ [% END %]
+ [% END %]
+ </div>
[% END %]
[% IF user.settings.display_quips.value == 'on' %]
@@ -84,7 +91,7 @@
'notequals', 'regexp', 'notregexp', 'lessthan', 'lessthaneq',
'greaterthan', 'greaterthaneq', 'changedbefore', 'changedafter',
'changedfrom', 'changedto', 'changedby', 'notsubstring', 'nowords',
- 'nowordssubstr', 'notmatches',
+ 'nowordssubstr', 'notmatches', 'isempty', 'isnotempty'
] %]
<ul class="search_description">
[% FOREACH desc_item = search_description %]
@@ -205,7 +212,7 @@
[% urlquerypart FILTER html %]&amp;ctype=csv&amp;human=1">CSV</a> |
<a href="buglist.cgi?
[% urlquerypart FILTER html %]&amp;title=
- [%- title FILTER html %]&amp;ctype=atom">Feed</a> |
+ [%- title FILTER uri %]&amp;ctype=atom">Feed</a> |
<a href="buglist.cgi?
[% urlquerypart FILTER html %]&amp;ctype=ics">iCalendar</a> |
<a href="colchange.cgi?
diff --git a/template/en/default/list/table.html.tmpl b/template/en/default/list/table.html.tmpl
index a074fcbd0..47dedb3cf 100644
--- a/template/en/default/list/table.html.tmpl
+++ b/template/en/default/list/table.html.tmpl
@@ -42,6 +42,7 @@
[% field_descs.reporter_realname = field_descs.reporter %]
[% field_descs.qa_contact_realname = field_descs.qa_contact %]
+[%# Setting maxlength => 0 means no limit. We set it for performance reasons. %]
[% abbrev =
{
"bug_severity" => { maxlength => 3 , title => "Sev" } ,
@@ -55,19 +56,21 @@
"qa_contact" => { maxlength => 30 , ellipsis => "..." , title => "QAContact" } ,
"qa_contact_realname" => { maxlength => 20 , ellipsis => "..." , title => "QAContact" } ,
"resolution" => { maxlength => 4 } ,
- "short_desc" => { wrap => 1 } ,
+ "short_desc" => { maxlength => 0, wrap => 1 } ,
"short_short_desc" => { maxlength => 60 , ellipsis => "..." , wrap => 1 } ,
- "status_whiteboard" => { title => "Whiteboard" , wrap => 1 } ,
- "keywords" => { wrap => 1 } ,
- "flagtypes.name" => { wrap => 1 } ,
+ "status_whiteboard" => { maxlength => 0, title => "Whiteboard" , wrap => 1 } ,
+ "keywords" => { maxlength => 0, wrap => 1 } ,
+ "dependson" => { maxlength => 0, wrap => 1 } ,
+ "blocked" => { maxlength => 0, wrap => 1 } ,
+ "flagtypes.name" => { maxlength => 0, wrap => 1 } ,
"component" => { maxlength => 8 , title => "Comp" } ,
"product" => { maxlength => 8 } ,
"version" => { maxlength => 5 , title => "Vers" } ,
"op_sys" => { maxlength => 4 } ,
"bug_file_loc" => { maxlength => 30 } ,
- "target_milestone" => { title => "TargetM" } ,
- "longdescs.count" => { title => "# Comments" },
- "percentage_complete" => { format_value => "%d %%" } ,
+ "target_milestone" => { maxlength => 0, title => "TargetM" } ,
+ "longdescs.count" => { maxlength => 0, title => "# Comments" },
+ "percentage_complete" => { maxlength => 0, format_value => "%d %%" } ,
}
%]
@@ -80,12 +83,15 @@
[%############################################################################%]
[% tableheader = BLOCK %]
- <table class="bz_buglist" cellspacing="0" cellpadding="4" width="100%">
+ <table class="bz_buglist sortable" cellspacing="0" cellpadding="4" width="100%">
+ <thead>
<tr class="bz_buglist_header bz_first_buglist_header">
[% IF dotweak %]
<th>&nbsp;</th>
[% END %]
- <th colspan="[% splitheader ? 2 : 1 %]" class="first-child">
+ <th colspan="[% splitheader ? 2 : 1 %]" class="first-child
+ sortable_column_0
+ sorted_[% lsearch(order_columns, 'bug_id') FILTER html %]">
<a href="buglist.cgi?
[% urlquerypart FILTER html %]&amp;order=
[% PROCESS new_order id='bug_id' %]
@@ -100,7 +106,7 @@
[% FOREACH id = displaycolumns %]
[% NEXT UNLESS loop.count() % 2 == 0 %]
[% column = columns.$id %]
- [% PROCESS columnheader %]
+ [% PROCESS columnheader key=loop.count() %]
[% END %]
</tr><tr class="bz_buglist_header">
@@ -112,7 +118,7 @@
[% FOREACH id = displaycolumns %]
[% NEXT IF loop.count() % 2 == 0 %]
[% column = columns.$id %]
- [% PROCESS columnheader %]
+ [% PROCESS columnheader key=loop.count() %]
[% END %]
[% ELSE %]
@@ -125,10 +131,13 @@
[% END %]
</tr>
+ </thead>
[% END %]
[% BLOCK columnheader %]
- <th colspan="[% splitheader ? 2 : 1 %]">
+ <th colspan="[% splitheader ? 2 : 1 %]"
+ class="sortable_column_[% key FILTER html %]
+ sorted_[% lsearch(order_columns, id) FILTER html %]">
<a href="buglist.cgi?[% urlquerypart FILTER html %]&amp;order=
[% PROCESS new_order %]
[%-#%]&amp;query_based_on=
@@ -151,13 +160,13 @@
[% END %]
[% BLOCK order_arrow %]
- [% IF order.match("^$id DESC") %]
+ [% IF order.search("^$id DESC") %]
<span class="bz_sort_order_primary">&#x25BC;</span>
- [% ELSIF order.match("^$id(,\\s*|\$)") %]
+ [% ELSIF order.search("^$id(,\\s*|\$)") %]
<span class="bz_sort_order_primary">&#x25B2;</span>
- [% ELSIF order.match("\\b$id DESC") %]
+ [% ELSIF order.search("\\b$id DESC") %]
<span class="bz_sort_order_secondary">&#x25BC;</span>
- [% ELSIF order.match("\\b$id(,\\s*|\$)") %]
+ [% ELSIF order.search("\\b$id(,\\s*|\$)") %]
<span class="bz_sort_order_secondary">&#x25B2;</span>
[% END %]
[% END %]
@@ -168,6 +177,7 @@
[% tableheader %]
+<tbody class="sorttable_body">
[% FOREACH bug = bugs %]
[% count = loop.count() %]
@@ -192,13 +202,24 @@
</td>
[% FOREACH column = displaycolumns %]
- <td [% 'style="white-space: nowrap"' IF NOT abbrev.$column.wrap %]
- class="bz_[% column FILTER css_class_quote %]_column">
- [% IF abbrev.$column.maxlength %]
+ [% col_abbrev = abbrev.$column %]
+ <td [% 'style="white-space: nowrap"' IF NOT col_abbrev.wrap %]
+ class="bz_[% column FILTER css_class_quote %]_column"
+ [% SWITCH column %]
+ [% CASE 'opendate' %]
+ sorttable_customkey="[% bug.opentime FILTER html %]"
+ [% CASE 'changeddate' %]
+ sorttable_customkey="[% bug.changedtime FILTER html %]"
+ [% CASE columns_sortkey.keys %]
+ [% SET sortkey = columns_sortkey.$column.${bug.$column} %]
+ sorttable_customkey="[% sortkey FILTER html %]"
+ [% END %]
+ >
+ [% IF col_abbrev.maxlength %]
<span title="[%- display_value(column, bug.$column) FILTER html %]">
[% END %]
- [% IF abbrev.$column.format_value %]
- [%- bug.$column FILTER format(abbrev.$column.format_value) FILTER html -%]
+ [% IF col_abbrev.format_value %]
+ [%- bug.$column FILTER format(col_abbrev.format_value) FILTER html -%]
[% ELSIF column == 'actual_time' ||
column == 'remaining_time' ||
column == 'estimated_time' %]
@@ -206,16 +227,20 @@
[%# Display the login name of the user if their real name is empty. %]
[% ELSIF column.match('_realname$') && bug.$column == '' %]
[% SET login_column = column.remove('_realname$') %]
- [% bug.${login_column}.truncate(abbrev.$column.maxlength,
- abbrev.$column.ellipsis) FILTER html %]
+ [% bug.${login_column}.truncate(col_abbrev.maxlength,
+ col_abbrev.ellipsis) FILTER html %]
[% ELSIF column == 'short_desc' || column == "short_short_desc" %]
<a href="show_bug.cgi?id=[% bug.bug_id FILTER html %]">
- [%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
+ [%- bug.$column.truncate(col_abbrev.maxlength, col_abbrev.ellipsis) FILTER html -%]
+ </a>
+ [% ELSIF bug_fields.$column.type == constants.FIELD_TYPE_BUG_ID %]
+ <a href="show_bug.cgi?id=[% bug.$column FILTER html %]">
+ [%- bug.$column.truncate(col_abbrev.maxlength, col_abbrev.ellipsis) FILTER html -%]
</a>
[% ELSE %]
- [%- display_value(column, bug.$column).truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
+ [%- display_value(column, bug.$column).truncate(col_abbrev.maxlength, col_abbrev.ellipsis) FILTER html -%]
[% END %]
- [% IF abbrev.$column.maxlength %]
+ [% IF col_abbrev.maxlength %]
</span>
[% END %]
</td>
@@ -223,11 +248,12 @@
</tr>
- [% IF loop.last() && time_info.time_present == 1 %]
+ [% IF time_info.time_present %]
[% PROCESS time_summary_line %]
[% END %]
[% END %]
+</tbody>
</table>
diff --git a/template/en/default/pages/bugzilla.dtd.tmpl b/template/en/default/pages/bugzilla.dtd.tmpl
new file mode 100644
index 000000000..f7fc1b4ad
--- /dev/null
+++ b/template/en/default/pages/bugzilla.dtd.tmpl
@@ -0,0 +1,179 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Dawn Endico <endico@mozilla.org>
+ # Dave Miller <justdave@syndicomm.com>
+ # Bradley Baetz <bbaetz@student.usyd.edu.au>
+ # Myk Mylez <myk@mozilla.org>
+ # Colin Ogilvie <mozilla@colinogilvie.co.uk>
+ # Joel Peshkin <bugreport@peshkin.net>
+ # Frédéric Buclin <LpSolit@gmail.com>
+ # Gervase Markham <gerv@gerv.net>
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ # David Lawrence <dkl@mozilla.com>
+ #
+ #%]
+[% USE Bugzilla %]
+<!ELEMENT [% "bugzilla" %] (bug+)>
+<!ATTLIST [% "bugzilla" %]
+ version CDATA #REQUIRED
+ urlbase CDATA #REQUIRED
+ maintainer CDATA #REQUIRED
+ exporter CDATA #IMPLIED
+>
+<!ELEMENT [% "bug" %] (bug_id,
+ (alias?,
+ creation_ts,
+ short_desc,
+ delta_ts,
+ reporter_accessible,
+ cclist_accessible,
+ classification_id,
+ classification,
+ product,
+ component,
+ version,
+ rep_platform,
+ op_sys,
+ bug_status,
+ resolution?,
+ dup_id?,
+ see_also*,
+ bug_file_loc?,
+ status_whiteboard?,
+ keywords*,
+ priority,
+ bug_severity,
+ target_milestone?,
+ dependson*,
+ blocked*,
+ everconfirmed,
+ reporter,
+ assigned_to,
+ cc*,
+ (estimated_time,
+ remaining_time,
+ actual_time,
+ deadline?)?,
+ qa_contact?,
+[% FOREACH field = Bugzilla.active_custom_fields %]
+ [%+ field.name FILTER xml -%]
+ [%- IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]*[% ELSE %]?[% END %],
+[% END %]
+ votes?,
+ token?,
+ group*,
+ flag*,
+ long_desc*,
+ attachment*)?)>
+<!ATTLIST [% "bug" %]
+ error (NotFound | NotPermitted | InvalidBugId) #IMPLIED
+>
+<!ELEMENT bug_id (#PCDATA)>
+<!ELEMENT alias (#PCDATA)>
+<!ELEMENT reporter_accessible (#PCDATA)>
+<!ELEMENT cclist_accessible (#PCDATA)>
+<!ELEMENT exporter (#PCDATA)>
+<!ELEMENT urlbase (#PCDATA)>
+<!ELEMENT bug_status (#PCDATA)>
+<!ELEMENT classification_id (#PCDATA)>
+<!ELEMENT classification (#PCDATA)>
+<!ELEMENT product (#PCDATA)>
+<!ELEMENT priority (#PCDATA)>
+<!ELEMENT version (#PCDATA)>
+<!ELEMENT rep_platform (#PCDATA)>
+<!ELEMENT assigned_to (#PCDATA)>
+<!ATTLIST assigned_to
+ name CDATA #REQUIRED
+>
+<!ELEMENT delta_ts (#PCDATA)>
+<!ELEMENT component (#PCDATA)>
+<!ELEMENT reporter (#PCDATA)>
+<!ATTLIST reporter
+ name CDATA #REQUIRED
+>
+<!ELEMENT target_milestone (#PCDATA)>
+<!ELEMENT bug_severity (#PCDATA)>
+<!ELEMENT creation_ts (#PCDATA)>
+<!ELEMENT qa_contact (#PCDATA)>
+<!ATTLIST qa_contact
+ name CDATA #REQUIRED
+>
+<!ELEMENT status_whiteboard (#PCDATA)>
+<!ELEMENT op_sys (#PCDATA)>
+<!ELEMENT resolution (#PCDATA)>
+<!ELEMENT dup_id (#PCDATA)>
+<!ELEMENT bug_file_loc (#PCDATA)>
+<!ELEMENT short_desc (#PCDATA)>
+<!ELEMENT keywords (#PCDATA)>
+<!ELEMENT dependson (#PCDATA)>
+<!ELEMENT blocked (#PCDATA)>
+<!ELEMENT everconfirmed (#PCDATA)>
+<!ELEMENT cc (#PCDATA)>
+<!ELEMENT see_also (#PCDATA)>
+<!ELEMENT votes (#PCDATA)>
+<!ELEMENT token (#PCDATA)>
+<!ELEMENT group (#PCDATA)>
+<!ATTLIST group
+ id CDATA #REQUIRED
+>
+<!ELEMENT estimated_time (#PCDATA)>
+<!ELEMENT remaining_time (#PCDATA)>
+<!ELEMENT actual_time (#PCDATA)>
+<!ELEMENT deadline (#PCDATA)>
+[% FOREACH field = Bugzilla.active_custom_fields %]
+<!ELEMENT [% field.name FILTER xml %] (#PCDATA)>
+[% END %]
+<!ELEMENT long_desc (commentid, attachid?, who, bug_when, work_time?, thetext)>
+<!ATTLIST long_desc
+ isprivate (0|1) #REQUIRED
+>
+<!ELEMENT commentid (#PCDATA)>
+<!ELEMENT who (#PCDATA)>
+<!ATTLIST who
+ name CDATA #REQUIRED
+>
+<!ELEMENT bug_when (#PCDATA)>
+<!ELEMENT work_time (#PCDATA)>
+<!ELEMENT thetext (#PCDATA)>
+<!ELEMENT attachment (attachid, date, delta_ts, desc, filename, type, size, attacher, token?, data?, flag*)>
+<!ATTLIST attachment
+ isobsolete (0|1) #REQUIRED
+ ispatch (0|1) #REQUIRED
+ isprivate (0|1) #REQUIRED
+ isurl (0|1) #REQUIRED
+>
+<!ELEMENT attacher (#PCDATA)>
+<!ELEMENT attachid (#PCDATA)>
+<!ELEMENT date (#PCDATA)>
+<!ELEMENT desc (#PCDATA)>
+<!ELEMENT filename (#PCDATA)>
+<!ELEMENT type (#PCDATA)>
+<!ELEMENT size (#PCDATA)>
+<!ELEMENT data (#PCDATA)>
+<!ATTLIST data
+ encoding (base64) #IMPLIED
+>
+<!ELEMENT flag EMPTY>
+<!ATTLIST flag
+ name CDATA #REQUIRED
+ id CDATA #REQUIRED
+ type_id CDATA #REQUIRED
+ status CDATA #REQUIRED
+ setter CDATA #REQUIRED
+ requestee CDATA #IMPLIED
+>
diff --git a/template/en/default/pages/fields.html.tmpl b/template/en/default/pages/fields.html.tmpl
index 2794e1cc4..568245653 100644
--- a/template/en/default/pages/fields.html.tmpl
+++ b/template/en/default/pages/fields.html.tmpl
@@ -62,34 +62,41 @@
</dt>
<dd class="unconfirmed">
This [% terms.bug %] has recently been added to the database.
- Nobody has confirmed that this [% terms.bug %] is valid. Users
+ Nobody has validated that this [% terms.bug %] is true. Users
who have the "canconfirm" permission set may confirm
- this [% terms.bug %], changing its state to
- <b>[% display_value("bug_status", "CONFIRMED") FILTER html %]</b>.
- Or, it may be directly resolved and marked
+ this [% terms.bug %], changing its state to [% display_value("bug_status", "NEW") FILTER html %]. Or, it may be
+ directly resolved and marked [% display_value("bug_status", "RESOLVED") FILTER html %].
+ </dd>
+ <dt>
+ <b>[% display_value("bug_status", "NEW") FILTER html %]</b>
+ </dt>
+ <dd>
+ This [% terms.bug %] has recently been added to the assignee's
+ list of [% terms.bugs %] and must be processed. [% terms.Bugs %] in
+ this state may be accepted, and become <b>[% display_value("bug_status", "ASSIGNED") FILTER html %]</b>, passed
+ on to someone else, and remain <b>[% display_value("bug_status", "NEW") FILTER html %]</b>, or resolved and marked
<b>[% display_value("bug_status", "RESOLVED") FILTER html %]</b>.
</dd>
- <dt class="confirmed">
- [% display_value("bug_status", "CONFIRMED") FILTER html %]
+ <dt>
+ <b>[% display_value("bug_status", "ASSIGNED") FILTER html %]</b>
</dt>
- <dd class="confirmed">
- This [% terms.bug %] is valid and has recently been filed.
- [%+ terms.Bugs %] in this state become
- <b>[% display_value("bug_status", "IN_PROGRESS") FILTER html %]</b>
- when somebody is working on them, or become resolved and marked
- <b>[% display_value("bug_status", "RESOLVED") FILTER html %]</b>.
+ <dd>
+ This [% terms.bug %] is not yet resolved, but is assigned to the
+ proper person. From here [% terms.bugs %] can be given to another
+ person and become <b>[% display_value("bug_status", "NEW") FILTER html %]</b>, or
+ resolved and become <b>[% display_value("bug_status", "RESOLVED") FILTER html %]</b>.
</dd>
- <dt class="in_progress">
- [% display_value("bug_status", "IN_PROGRESS") FILTER html %]
+ <dt>
+ <b>[% display_value("bug_status", "REOPENED") FILTER html %]</b>
</dt>
- <dd class="in_progress">
- This [% terms.bug %] is not yet resolved, but is assigned to the
- proper person who is working on the [% terms.bug %]. From here,
- [%+ terms.bugs %] can be given to another person and become
- <b>[% display_value("bug_status", "CONFIRMED") FILTER html %]</b>, or
- resolved and become
+ <dd>
+ This [% terms.bug %] was once resolved, but the resolution was
+ deemed incorrect. For example, a <b>[% display_value("resolution", "WORKSFORME") FILTER html %]</b> [% terms.bug %] is
+ <b>[% display_value("bug_status", "REOPENED") FILTER html %]</b> when more information shows up and
+ the [% terms.bug %] is now reproducible. From here [% terms.bugs %] are
+ either marked <b>[% display_value("bug_status", "ASSIGNED") FILTER html %]</b> or
<b>[% display_value("bug_status", "RESOLVED") FILTER html %]</b>.
</dd>
@@ -124,9 +131,10 @@
[% display_value("bug_status", "VERIFIED") FILTER html %]
</dt>
<dd class="verified">
- QA has looked at the [% terms.bug %] and the resolution and
- agrees that the appropriate resolution has been taken. This is
- the final status for [% terms.bugs %].
+ QA has looked at the [% terms.bug %] and the resolution and
+ agrees that the appropriate resolution has been taken.
+ Any zombie [% terms.bugs %] who choose to walk the earth again must
+ do so by becoming <b>[% display_value("bug_status", "REOPENED") FILTER html %]</b>.
</dd>
[% Hook.process('closed-status') %]
@@ -163,10 +171,9 @@
</dt>
<dd class="duplicate">
The problem is a duplicate of an existing [% terms.bug %].
- When [% terms.abug %] is marked as a
- <b>[% display_value("resolution", "DUPLICATE") FILTER html %]</b>,
- you will see which [% terms.bug %] it is a duplicate of,
- next to the resolution.
+ Marking [% terms.abug %] duplicate requires the [% terms.bug %]#
+ of the duplicating [% terms.bug %] and will at least put
+ that [% terms.bug %] number in the description field.
</dd>
<dt class="worksforme">
diff --git a/template/en/default/pages/quicksearch.html.tmpl b/template/en/default/pages/quicksearch.html.tmpl
index 901f05467..c43047d9f 100644
--- a/template/en/default/pages/quicksearch.html.tmpl
+++ b/template/en/default/pages/quicksearch.html.tmpl
@@ -303,6 +303,14 @@
<strong>#</strong><em>value</em>
</td>
</tr>
+ <tr>
+ <td class="field_name">Comment Searching</td>
+ <td class="field_nickname">
+ Allows overriding of the comment searching preference.<br>
+ "<strong>++comments</strong>" will always enable comment searching.<br>
+ "<strong>--comments</strong>" will always disable searching.<br>
+ </td>
+ </tr>
[% IF Param('usestatuswhiteboard') %]
<tr>
<td class="field_name">[% field_descs.short_desc FILTER html %]
diff --git a/template/en/default/reports/components.html.tmpl b/template/en/default/reports/components.html.tmpl
index ef7d5ae6d..b2a21ccc1 100644
--- a/template/en/default/reports/components.html.tmpl
+++ b/template/en/default/reports/components.html.tmpl
@@ -22,6 +22,7 @@
[%# INTERFACE:
# product: object. The product for which we want to display component
# descriptions.
+ # component: string. The name of the component to hilight in the browser
#%]
[% title = BLOCK %]
@@ -39,6 +40,8 @@
[% numcols = 2 %]
[% END %]
+<h2>[% mark FILTER html %]</h2>
+
<table cellpadding="0" cellspacing="0" id="components_header_table">
<tr>
<td class="instructions">
@@ -81,9 +84,11 @@
[%############################################################################%]
[% BLOCK describe_comp %]
- <tr id="[% comp.name FILTER html %]">
+ <tr id="[% comp.name FILTER html %]"
+ [%- IF comp.name == component_mark %] class="component_hilite"[% END %]>
<td rowspan="2" class="component_name">
- <a href="buglist.cgi?product=
+ <a name="[% comp.name FILTER html %]"
+ href="buglist.cgi?product=
[%- product.name FILTER uri %]&amp;component=
[%- comp.name FILTER uri %]&amp;resolution=---">
[% comp.name FILTER html %]</a>
@@ -97,7 +102,7 @@
</td>
[% END %]
</tr>
- <tr>
+ <tr[% IF comp.name == component_mark %] class="component_hilite"[% END %]>
<td colspan="[% numcols - 1 %]" class="component_description">
[% comp.description FILTER html_light %]
</td>
diff --git a/template/en/default/reports/report.html.tmpl b/template/en/default/reports/report.html.tmpl
index 94725ae81..38b64df0b 100644
--- a/template/en/default/reports/report.html.tmpl
+++ b/template/en/default/reports/report.html.tmpl
@@ -81,7 +81,9 @@
%]
[% IF debug %]
- <p>[% query FILTER html %]</p>
+ [% FOREACH query = queries %]
+ <p>[% query.sql FILTER html %]</p>
+ [% END %]
[% END %]
<div align="center">
diff --git a/template/en/default/request/email.txt.tmpl b/template/en/default/request/email.txt.tmpl
index fb957484b..f05059c1a 100644
--- a/template/en/default/request/email.txt.tmpl
+++ b/template/en/default/request/email.txt.tmpl
@@ -25,7 +25,8 @@
[% bugidsummary = bug.bug_id _ ': ' _ bug.short_desc %]
[% attidsummary = attachment.id _ ': ' _ attachment.description %]
[% flagtype_name = flag ? flag.type.name : old_flag.type.name %]
-[% statuses = { '+' => "granted" , '-' => 'denied' , 'X' => "canceled" ,
+[%# Upstreaming: denied (bug 621883) %]
+[% statuses = { '+' => "granted" , '-' => 'not granted' , 'X' => "canceled" ,
'?' => "asked" } %]
[% to_identity = "" %]
@@ -53,6 +54,10 @@ Subject: [% flagtype_name %] [%+ subject_status %]: [[% terms.Bug %] [%+ bug.bug
[Attachment [% attachment.id %]] [% attachment.description FILTER clean_text %][% END %]
Date: [% date %]
X-Bugzilla-Type: request
+[%- IF flag.requestee %]
+X-Bugzilla-Flag-Requestee: [% flag.requestee.email %]
+[% END %]
+[%+ INCLUDE "email/header-common.txt.tmpl" %]
[%+ threadingmarker %]
[%+ USE wrap -%]
diff --git a/template/en/default/request/queue.html.tmpl b/template/en/default/request/queue.html.tmpl
index 57650de55..0ed14bad7 100644
--- a/template/en/default/request/queue.html.tmpl
+++ b/template/en/default/request/queue.html.tmpl
@@ -25,10 +25,6 @@
[% PROCESS global/header.html.tmpl
title="Request Queue"
- style = "
- table.requests th { text-align: left; }
- table#filtering th { text-align: right; }
- "
onload="var f = document.request_form; selectProduct(f.product, f.component, null, null, 'Any');"
javascript_urls=["js/productform.js", "js/field.js"]
style_urls = ['skins/standard/buglist.css']
@@ -161,10 +157,22 @@ to some group are shown by default.
} %]
[% PROCESS "global/select-menu.html.tmpl" name="group" options=groups default=cgi.param('group') %]
</td>
+ </tr>
+ <tr>
+ <th></th>
+ <td>
+ <label><input type="radio" name="do_union" value="0"
+ [% 'checked="checked"' IF !cgi.param('do_union') %]>AND *</label>
+ <label><input type="radio" name="do_union" value="1"
+ [% 'checked="checked"' IF cgi.param('do_union') %]>OR *</label>
+ </td>
+ <td colspan="3"></td>
<td><input type="submit" id="filter" value="Filter"></td>
</tr>
</table>
+ <p>(* The logical conjunction/disjunction between the requester
+ and the requestee)</p>
</form>
[% column_headers = {
@@ -198,7 +206,10 @@ to some group are shown by default.
[% PROCESS start_new_table %]
[% END %]
[% buglist.${request.bug_id} = 1 %]
- <tr>
+
+ <tr class="bz_bugitem bz_[% request.bug_severity FILTER css_class_quote -%]
+ bz_[% request.priority FILTER css_class_quote -%]
+ bz_[% request.bug_status FILTER css_class_quote %]">
[% FOREACH column = display_columns %]
[% NEXT IF column == group_field || excluded_columns.contains(column) %]
<td>
@@ -238,7 +249,7 @@ to some group are shown by default.
[% BLOCK display_bug %]
<a href="show_bug.cgi?id=[% request.bug_id %]"
[%- ' class="bz_secure"' IF request.restricted %]>
- [% request.bug_id %]: [%+ request.bug_summary FILTER html %]</a>
+ [% request.bug_id %] ([% request.priority FILTER html %]/[% request.bug_severity FILTER html %]): [%+ request.bug_summary FILTER html %]</a>
[% END %]
[% BLOCK display_attachment %]
diff --git a/template/en/default/search/boolean-charts.html.tmpl b/template/en/default/search/boolean-charts.html.tmpl
index 878589cea..3fb1f8eae 100644
--- a/template/en/default/search/boolean-charts.html.tmpl
+++ b/template/en/default/search/boolean-charts.html.tmpl
@@ -47,6 +47,8 @@
"changedby",
"matches",
"notmatches",
+ "isempty",
+ "isnotempty",
] %]
<div class="bz_section_title" id="custom_search_filter">
@@ -78,6 +80,10 @@
<script type="text/javascript" src="[% 'js/history.js/native.history.js' FILTER mtime %]"></script>
<script type="text/javascript">
redirect_html4_browsers();
+ [%# These are alternative labels for the AND and OR options in and_all_select %]
+ var cs_and_label = 'Match ALL of the following:';
+ var cs_or_label = 'Match ANY of the following:';
+ cs_reconfigure('custom_search_last_row');
</script>
</div>
@@ -134,7 +140,8 @@
(
[% indent_level = indent_level + 1 %]
[% ELSIF condition.f == "CP" %]
- <input type="hidden" name="f[% cond_num FILTER html %]" value="CP">
+ <input type="hidden" name="f[% cond_num FILTER html %]"
+ id="f[% cond_num FILTER html %]" value="CP">
)
[% ELSE %]
<select name="f[% cond_num FILTER html %]" title="Field"
@@ -178,9 +185,11 @@
<div class="any_all_select">
<select name="[% name FILTER html %]" id="[% name FILTER html %]"
onchange="fix_query_string(this)">
- <option value="AND">Match ALL of the following:</option>
+ <option value="AND">Match ALL of the following separately:</option>
<option value="OR" [% ' selected="selected"' IF selected == "OR" %]>
- Match ANY of the following:</option>
+ Match ANY of the following separately:</option>
+ <option value="AND_G" [% ' selected' IF selected == "AND_G" %]>
+ Match ALL of the following against the same field:</option>
</select>
[% IF with_advanced_link %]
<a id="custom_search_advanced_controller"
diff --git a/template/en/default/search/field.html.tmpl b/template/en/default/search/field.html.tmpl
index defc94cc3..19f199692 100644
--- a/template/en/default/search/field.html.tmpl
+++ b/template/en/default/search/field.html.tmpl
@@ -115,7 +115,7 @@
<select name="[% field.name FILTER html%]"
id="[% field.name FILTER html %]"
[% IF onchange %] onchange="[% onchange FILTER html %]"[% END %]
- multiple="multiple" size="7">
+ multiple="multiple" size="9">
[% legal_values = ${field.name} %]
[% IF field.name == "component" %]
[% legal_values = ${"component_"} %]
diff --git a/template/en/default/search/form.html.tmpl b/template/en/default/search/form.html.tmpl
index 241ade088..5a97dd4d3 100644
--- a/template/en/default/search/form.html.tmpl
+++ b/template/en/default/search/form.html.tmpl
@@ -333,6 +333,7 @@ TUI_hide_default('information_query');
<select name="emailtype[% n %]">
[% FOREACH qv = [
{ name => "substring", description => "contains" },
+ { name => "notsubstring", description => "doesn't contain" },
{ name => "exact", description => "is" },
{ name => "notequals", description => "is not" },
{ name => "regexp", description => "matches regexp" },
diff --git a/template/en/default/search/search-google.html.tmpl b/template/en/default/search/search-google.html.tmpl
new file mode 100644
index 000000000..080887abb
--- /dev/null
+++ b/template/en/default/search/search-google.html.tmpl
@@ -0,0 +1,57 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is the Mozilla Foundation
+ # Portions created by the Initial Developers are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Search " _ terms.Bugs _ " using Google"
+%]
+
+[% WRAPPER search/tabs.html.tmpl %]
+
+<p>
+ Use the <a href="http://www.google.com">Google</a> search engine to search
+ for [% terms.Bugzilla +%] [%+ terms.bugs %]. Find the [% terms.bugs %] you are
+ looking for by entering words that best describe it.
+</p>
+
+<p>
+ For example, if the [% terms.bug %] you are looking for is a browser crash when
+ you go to a secure web site with an embedded Flash animation, you might search
+ for "crash secure SSL flash".
+</p>
+
+<p>
+ <span style="color:red;">*</span>
+ Google only indexes publicly viewable [% terms.bugs %] and all may not be represented.
+<p>
+
+<form method="get" action="http://www.google.com/search">
+<input type="hidden" name="sitesearch" value="bugzilla.mozilla.org">
+ <nobr>
+ <input type="text" name="q" size="60" maxlength="255" value="">
+ <input type="submit" value="Search">
+ </nobr>
+</form>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
+
diff --git a/template/en/default/search/search-instant.html.tmpl b/template/en/default/search/search-instant.html.tmpl
new file mode 100644
index 000000000..5d75d1996
--- /dev/null
+++ b/template/en/default/search/search-instant.html.tmpl
@@ -0,0 +1,85 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Instant Search"
+ javascript_urls = [ 'extensions/GuidedBugEntry/web/js/products.js',
+ 'js/instant-search.js', ]
+ yui = [ 'datatable', 'container' ]
+%]
+
+[% UNLESS default.exists('product') && default.product.size %]
+ [% default.product = [ 'Firefox' ] %]
+[% END %]
+
+<script>
+YAHOO.bugzilla.instantSearch.setLabels( {
+ id: "[% field_descs.bug_id FILTER js %]",
+ summary: "[% field_descs.short_desc FILTER js %]",
+ component: "[% field_descs.component FILTER js %]",
+ status: "[% field_descs.bug_status FILTER js %]",
+});
+</script>
+
+[% WRAPPER search/tabs.html.tmpl %]
+
+<p>
+ This page provides instant results; however, only the [% terms.bug %]'s summary
+ is searched. Products related to the selected product may also be searched.
+</p>
+
+<table>
+ <tr>
+ <td align="right" valign="baseline">
+ <b><label for="product">Product:</label></b>
+ </td>
+ <td>
+ <select name="product" id="product">
+ [% IF Param('useclassification') %]
+ [% FOREACH c = classification %]
+ <optgroup label="[% c.name FILTER html %]">
+ [% FOREACH p = user.get_selectable_products(c.id) %]
+ [% IF p.components.size %]
+ <option value="[% p.name FILTER html %]"
+ [% " selected" IF lsearch(default.product, p.name) != -1 %]>
+ [% p.name FILTER html %]
+ </option>
+ [% END %]
+ [% END %]
+ </optgroup>
+ [% END %]
+ [% ELSE %]
+ [% FOREACH p = product %]
+ <option value="[% p.name FILTER html %]"
+ [% " selected" IF lsearch(default.product, p.name) != -1 %]>
+ [% p.name FILTER html %]
+ </option>
+ [% END %]
+ [% END %]
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td align="right" valign="baseline">
+ <b><label for="content">Words:</label></b>
+ </td>
+ <td>
+ <input id="content" spellcheck="true" size="60"
+ value="[% default.content.0 FILTER html %]">
+ </td>
+ </tr>
+</table>
+<br>
+
+<div id="results"></div>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/search/search-specific.html.tmpl b/template/en/default/search/search-specific.html.tmpl
index 9ef299425..7e5de2c4a 100644
--- a/template/en/default/search/search-specific.html.tmpl
+++ b/template/en/default/search/search-specific.html.tmpl
@@ -98,7 +98,7 @@ for "crash secure SSL flash".
<label for="content">Words:</label>
</th>
<td>
- <input name="content" size="40" id="content"
+ <input name="content" size="60" id="content"
value="[% default.content.0 FILTER html %]">
<script type="text/javascript"> <!--
document.forms['queryform'].content.focus();
@@ -107,6 +107,15 @@ for "crash secure SSL flash".
</td>
</tr>
<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="hidden" name="comments" value="0">
+ <input type="checkbox" id="comments" name="comments"
+ value="1" [% 'checked' IF cgi.param("comments") %]>
+ <label for="comments">Search comments</label>
+ </td>
+ </tr>
+ <tr>
<td></td>
<td>
diff --git a/template/en/default/search/tabs.html.tmpl b/template/en/default/search/tabs.html.tmpl
index 119b30fde..26ad4f39b 100644
--- a/template/en/default/search/tabs.html.tmpl
+++ b/template/en/default/search/tabs.html.tmpl
@@ -24,10 +24,14 @@
#%]
[% WRAPPER global/tabs.html.tmpl
- tabs = [ { name => 'specific', label => "Simple Search",
+ tabs = [ { name => 'instant', label => "Instant Search",
+ link => "query.cgi?format=instant" },
+ { name => 'specific', label => "Simple Search",
link => "query.cgi?format=specific" },
{ name => 'advanced', label => "Advanced Search",
- link => "query.cgi?format=advanced" } ]
+ link => "query.cgi?format=advanced" },
+ { name => 'google', label => 'Google Search',
+ link => "query.cgi?format=google" } ]
current_tab_name = query_format || format || "advanced"
%]
diff --git a/userprefs.cgi b/userprefs.cgi
index f0d5a8e53..e614d8111 100755
--- a/userprefs.cgi
+++ b/userprefs.cgi
@@ -338,6 +338,47 @@ sub SaveEmail {
$dbh->bz_commit_transaction();
}
+
+ ###########################################################################
+ # Ignore Bugs
+ ###########################################################################
+ my %ignored_bugs = map { $_->{'id'} => 1 } @{$user->bugs_ignored};
+
+ # Validate the new bugs to ignore by checking that they exist and also
+ # if the user gave an alias
+ my @add_ignored = split(/[\s,]+/, $cgi->param('add_ignored_bugs'));
+ @add_ignored = map { Bugzilla::Bug->check($_)->id } @add_ignored;
+ map { $ignored_bugs{$_} = 1 } @add_ignored;
+
+ # Remove any bug ids the user no longer wants to ignore
+ foreach my $key (grep(/^remove_ignored_bug_/, $cgi->param)) {
+ my ($bug_id) = $key =~ /(\d+)$/;
+ delete $ignored_bugs{$bug_id};
+ }
+
+ # Update the database with any changes made
+ my ($removed, $added) = diff_arrays([ map { $_->{'id'} } @{$user->bugs_ignored} ],
+ [ keys %ignored_bugs ]);
+
+ if (scalar @$removed || scalar @$added) {
+ $dbh->bz_start_transaction();
+
+ if (scalar @$removed) {
+ $dbh->do('DELETE FROM email_bug_ignore WHERE user_id = ? AND ' .
+ $dbh->sql_in('bug_id', $removed),
+ undef, $user->id);
+ }
+ if (scalar @$added) {
+ my $sth = $dbh->prepare('INSERT INTO email_bug_ignore
+ (user_id, bug_id) VALUES (?, ?)');
+ $sth->execute($user->id, $_) foreach @$added;
+ }
+
+ # Reset the cache of ignored bugs if the list changed.
+ delete $user->{bugs_ignored};
+
+ $dbh->bz_commit_transaction();
+ }
}
@@ -345,9 +386,9 @@ sub DoPermissions {
my $dbh = Bugzilla->dbh;
my $user = Bugzilla->user;
my (@has_bits, @set_bits);
-
+
my $groups = $dbh->selectall_arrayref(
- "SELECT DISTINCT name, description FROM groups WHERE id IN (" .
+ "SELECT DISTINCT name, description FROM groups WHERE id IN (" .
$user->groups_as_string . ") ORDER BY name");
foreach my $group (@$groups) {
my ($nam, $desc) = @$group;
diff --git a/whine.pl b/whine.pl
index ad6067228..e6161cfeb 100755
--- a/whine.pl
+++ b/whine.pl
@@ -453,7 +453,7 @@ sub run_queries {
'user' => $args->{'recipient'}, # the search runs as the recipient
);
# If a query fails for whatever reason, it shouldn't kill the script.
- my $sqlquery = eval { $search->sql };
+ my $data = eval { $search->data };
if ($@) {
print STDERR get_text('whine_query_failed', { query_name => $thisquery->{'name'},
author => $args->{'author'},
@@ -461,15 +461,12 @@ sub run_queries {
next;
}
- $sth = $dbh->prepare($sqlquery);
- $sth->execute;
-
- while (my @row = $sth->fetchrow_array) {
+ foreach my $row (@$data) {
my $bug = {};
for my $field (@searchfields) {
my $fieldname = $field;
$fieldname =~ s/^bugs\.//; # No need for bugs.whatever
- $bug->{$fieldname} = shift @row;
+ $bug->{$fieldname} = shift @$row;
}
if ($thisquery->{'onemailperbug'}) {
diff --git a/xml.cgi b/xml.cgi
new file mode 100755
index 000000000..ce6a7c39b
--- /dev/null
+++ b/xml.cgi
@@ -0,0 +1,41 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Dawn Endico <endico@mozilla.org>
+# Terry Weissman <terry@mozilla.org>
+# Gervase Markham <gerv@gerv.net>
+
+use strict;
+
+use lib qw(. lib);
+use Bugzilla;
+
+my $cgi = Bugzilla->cgi;
+
+# Convert comma/space separated elements into separate params
+my @ids = ();
+
+if (defined $cgi->param('id')) {
+ @ids = split (/[, ]+/, $cgi->param('id'));
+}
+
+my $ids = join('', map { $_ = "&id=" . $_ } @ids);
+
+print $cgi->redirect("show_bug.cgi?ctype=xml$ids");
diff --git a/xt/lib/Bugzilla/Test/Search/FieldTest.pm b/xt/lib/Bugzilla/Test/Search/FieldTest.pm
index 283a90d16..bd5fd905a 100644
--- a/xt/lib/Bugzilla/Test/Search/FieldTest.pm
+++ b/xt/lib/Bugzilla/Test/Search/FieldTest.pm
@@ -544,13 +544,13 @@ sub do_tests {
my $sql;
TODO: {
local $TODO = $search_broken if $search_broken;
- lives_ok { $sql = $search->sql } "$name: generate SQL";
+ lives_ok { $sql = $search->_sql } "$name: generate SQL";
}
my $results;
SKIP: {
skip "Can't run SQL without any SQL", 1 if !defined $sql;
- $results = $self->_test_sql($sql);
+ $results = $self->_test_sql($search);
}
$self->_test_content($results, $sql);
@@ -567,12 +567,11 @@ sub _test_search_object_creation {
}
sub _test_sql {
- my ($self, $sql) = @_;
- my $dbh = Bugzilla->dbh;
+ my ($self, $search) = @_;
my $name = $self->name;
my $results;
- lives_ok { $results = $dbh->selectall_arrayref($sql) } "$name: Run SQL Query"
- or diag($sql);
+ lives_ok { $results = $search->data } "$name: Run SQL Query"
+ or diag($search->_sql);
return $results;
}